设A
、B
和C
为三个数组,每个数组包含N
个数:
A = a[0], a[1], a[2], ..., a[N-1]
B = b[0], b[1], b[2], ..., b[N-1]
C = c[0], c[1], c[3], ..., c[N-1]
我想从A
中选择最好的k < N
元素,从B
中选择最好的k < N
元素,以便使它们的值的总和最大化。有趣的变化是:如果元素i
是从A
和B
(其中i
在{0, ..., N-1}
中是索引)中选择的,那么它们将贡献c[i]
而不是贡献a[i] + b[i]
的这些元素
乍一看,我觉得这似乎很简单,但我想得越多,它就参与得越多
我最终在寻找一个Python实现,但在这个阶段,我只是想弄清楚什么是一个高效的算法
为了澄清,算法的输入是3N x 1
数组A
、B
和C
,以及k
的整数值。预期的输出是两个k x 1
索引列表,定义了A
和B
(和C
)元素的值最大化组合
例如,假设k = 2
,N = 4
并让
A = a[0], a[1], a[2], a[3] = 3, 1, 1, 0
B = b[0], b[1], b[2], b[3] = 1, 3, 0, 1
C = c[0], c[1], c[2], c[3] = 4, 4, 3, 2
即使在这个简单的例子中,也有许多可能的组合。例如,如果元素i = 0, 2
是从A
中选择的,元素j = 1, 3
是从B
中选择的,那么总值将是a[0] + a[2] + b[1] + b[3] = 8
另一方面,如果元素i = 0, 1
和j = 0, 1
将从A
和B
中选择,则特殊的扭曲适用:不是产生a[0] + a[1] + b[0] + b[1]
,而是由c[0] + c[1] = 8
给出总值
在本例中,使总值最大化的元素组合由来自A
的i = 0, 2
和来自B
的元素j = 1, 2
给出。这将产生a[0] + b[1] + c[2] = 9
的总值,可以验证该值比任何其他组合都高
下面是提交的3个解决方案的快速比较。首先,我检查了所有这些,它们都给出了预期的结果。作为旁注,它们都不要求C
的元素弱于A
和B
中相应元素的总和,因此我在绩效评估中放弃了这一假设
以下是我运行的内容:
import numpy as np
from utils import tic, toc # simple wrapper to time.perf_counter()
k, N = 10, 1000
A = list(np.random.random_sample([N]))
B = list(np.random.random_sample([N]))
C = list(np.random.random_sample([N]))
tic()
print(optimal_choices(k, A, B, C)) # solution by btilly
toc()
tic()
print(maxPicks(A.copy(), B.copy(), C.copy(), k)) # solution by Eric T-M
toc()
tic()
print(maxSum(A, B, C, k)) # solution by Alain T.
toc()
我测试了k
和N
的各种组合。似乎只要k
很小,@btilly的算法就可以在N
中很好地伸缩@Alain-T.的算法正好相反,当k
相对于N
较大时,表现良好。综上所述,@Eric-T-M的算法做得最好,在k
和N
中都能很好地伸缩
小问题:k=10和N=500
小k、大N:k=10和N=1000
大k、小N:k=80和N=100
中等问题:k=50和N=1000
大问题1:k=10和N=1\u 000
大问题2:k=1_000和N=100_000
(对于基准测试,我删除了Alain T.代码中的排序,以使其具有可比性。)
这可以用动态规划来解决
如果将A和B展开为一个索引对列表,其中包含各自的和(应用C中的异常),则可以迭代地获取最大和,并在每个步骤中排除相应的对。这将在每次迭代时从剩余对中选择可能的最高总数:
输出:
试试这个。它需要
O(N^2)
时间,而且相当简单下面是它的工作原理:
基本情况应该是不言自明的。否则,我们将比较
A
中所有条目的最大值和B
中所有条目的最大值与C
中所有条目的最大值之和。如果此总和大于从A
和B
中选取这些条目的安全值,但在进行更多选取之前,我们需要将选取的条目以及它们在C
中的对应条目设置为负值。作为旁注,我确实假设a、B和C中的所有值最初都是非负的,因此通过将它们设置为负,我们禁止我们的算法再次拾取它们。如果这个假设是错误的,您可能希望将这些值设置为极端负的值,以禁止重复拾取。我们还看到,如果我们选择了A[i]
,那么B[i]
的值现在是C[i]-A[i]
的值,因为选择B[i]
将丢失A[i]
中的值,如果我们选择B[j]
,则为条目A[j]
提供相同的C[i]
中的值另一方面,如果}将更有价值。此时我们知道我们不想重新选择
C
中的最大条目大于或等于aMax+bMax
,我们希望选择它(通过选择A
和B
中的相应条目,因为A
和B
中的其他条目选择或仅仅是^A[i],B[i]
,或C[i]
,所以我们将它们都设置为负值相关问题 更多 >
编程相关推荐