【发布时间】:2020-11-07 05:47:10
【问题描述】:
来自 Coursera 的算法工具箱课程。
问题介绍
给你一套金条,你的目标是尽可能多地把金条装进你的包里。每个小节只有一个副本,对于每个小节,您可以选择或不接受(因此您不能选择小节的一小部分)。
问题描述
任务。给了????金条,找到装进一袋容量的最大黄金重量????。输入格式。输入的第一行包含容量 ????一个背包和号码????金条。下一行包含 ????整数 ????0,????1, . . . ,??????????−1 定义金条的重量。
约束。 1≤???? ≤ 10^4; 1≤???? ≤ 300; 0 ≤ ??0, . . . , ????????−1 ≤ 10^5.
输出格式。输出能装进一个背包容量的最大黄金重量????。
我在 Python 中使用动态编程的解决方案:
def optimal_weight(W, w):
golds = [0] + w
gold_dict = {}
for i in range(0, W+1):
gold_dict[(i, golds[0])] = 0
for i in golds:
gold_dict[(0, i)] = 0
for i in range(1, len(golds)):
for weight in range(1, W+1):
gold_dict[(weight, golds[i])] = gold_dict[(weight, golds[i-1])]
if golds[i] <= weight:
val = gold_dict[(weight-golds[i], golds[i-1])] + golds[i]
if gold_dict[(weight, golds[i])] < val:
gold_dict[(weight, golds[i])] = val
return max(gold_dict.values())
第二个输入是金条列表,其权重为整数。对于输入:
10, [1, 4, 8]
结果应该是整数 9(即 1+8)。
我已经测试了一个示例列表,其中包括一些极端值,例如:
1, [0]
对于他们所有人来说,结果似乎都是正确的。但是,最终测试一直显示由于错误答案而未通过其中一项测试。因此,我的代码中必须存在错误。然而我很难找到它。 (分配测试不会发布测试参数,因此我无法获得触发错误答案的输入)
有人可以告知潜在的问题是什么吗?即使是提示也将不胜感激。非常感谢。
编辑:
我添加了 main 函数来显示如何读取输入,但我不认为这与潜在的错误有关:
if __name__ == '__main__':
input = sys.stdin.read()
W, n, *w = list(map(int, input.split()))
print(optimal_weight(W, w))
sys.stdin 将读取带有示例输入的测试 txt 文件,如下所示:
10 3
1 4 8
这意味着一个袋子的容量为 10、3 根金条,重量分别为 1、4、8 个。
main方法自带问题,不做修改。
Edit2 答案:
感谢 Arty 在下面的建议,问题来自使用 gold[i] 作为 gold_dict 元组键的一部分。如果有多个具有相同权重的金条,它们在 gold[] 列表中的索引将不同(不同的 i)但它们的 gold[i] 值将相同。在这种情况下,元组键 (weight, gold[i]) 可能会引用错误的对象。
我对 Arty 的正确代码和错误代码进行了随机测试,以找到可能触发错误的参数,该错误在运行大约 3000 次后出现:
209 38
16, 21, 21, 96, 129, 144, 159, 253, 254, 259, 259, 267, 285, 290, 304, 351, 351, 383, 411, 429, 493, 494, 527, 530, 534, 596, 619, 625, 692, 717, 727, 727, 745, 772, 833, 853, 856, 946
对于本例,我的代码将得到答案 208,而正确答案是 202。
修复其实很简单,只要把所有关键元组的gold[i]改为i即可:
def optimal_weight(W, w):
golds = [0] + w
gold_dict = {}
for i in range(0, W+1):
gold_dict[(i, 0)] = 0
for i in range(0, len(golds)):
gold_dict[(0, i)] = 0
for i in range(1, len(golds)):
for weight in range(1, W+1):
gold_dict[(weight, i)] = gold_dict[(weight, (i-1))]
if golds[i] <= weight:
val = gold_dict[(weight-golds[i], i-1)] + golds[i]
if gold_dict[(weight, i)] < val:
gold_dict[(weight, i)] = val
return max(gold_dict.values())
【问题讨论】:
-
您遗漏了读取输入的代码。另外,失败的测试是否有一个暗示性的名称,即使你没有得到参数?
-
感谢您的回复,不,除了确定产生“错误答案”这一事实之外,失败的测试不会提供任何信息(但这确实意味着算法没有超过运行时间或内存使用限制)。我删除了主要功能以简化问题本身,但又将它们添加回来。
-
@rich_monkey_2004 我将实施我的解决方案in my answer here,也尝试纠正您的解决方案,看看那里!