C++ 无界背包与经典背包的比较
我在网上读过两个截然不同的问题0-1背包问题和无界背包问题。我发现这两个问题都是通过动态规划来解决的,但有两种不同的方式。 如果用二维数组求解0-1背包问题,则无界背包问题仅使用一维数组 你可以读更多的书C++ 无界背包与经典背包的比较,c++,algorithm,dynamic-programming,C++,Algorithm,Dynamic Programming,我在网上读过两个截然不同的问题0-1背包问题和无界背包问题。我发现这两个问题都是通过动态规划来解决的,但有两种不同的方式。 如果用二维数组求解0-1背包问题,则无界背包问题仅使用一维数组 你可以读更多的书 正如我所知,这两个问题的区别在于0-1背包问题只包含有限数量的东西,而无界背包问题允许获取任何资源的一个或多个实例。但是,我不知道为什么它改变了解决这个问题的方式?你能告诉我原因吗?表格方法更易于解释和调试,这就是为什么算法说明通常显示这种方式 注意,对于0-1背包问题,我们必须排除重复使用物
正如我所知,这两个问题的区别在于0-1背包问题只包含有限数量的东西,而无界背包问题允许获取任何资源的一个或多个实例。但是,我不知道为什么它改变了解决这个问题的方式?你能告诉我原因吗?表格方法更易于解释和调试,这就是为什么算法说明通常显示这种方式 注意,对于0-1背包问题,我们必须排除重复使用物品两次的可能性。所以在外循环的每一步,我们都使用当前项更新以前的最佳结果 但是我们只使用表的最后一行(查看索引
i
和i-1
),因此我们可以仅使用当前行和最后一行将表大小减小到2 x容量
此外,我们可以使用一维数组的方法,应用一个技巧——为了避免重用项,我们可以执行反向遍历
下面的Python代码使用来自wiki页面的数据,并显示了表和线性数组实现
wt = [23,26,20,18,32,27,29,26,30,27]
val = [505,352,458,220,354,414,498,545,473,543]
def knap1(w,v, cap):
n = len(w)
m = [[0]*(cap+1) for _ in range(n)]
for i in range(n):
for j in range(cap + 1):
if w[i] > j:
m[i][j] = m[i-1][j]
else:
m[i][j] = max(m[i-1][j], m[i-1][j-w[i]] + v[i])
return m[n-1][cap]
def knap2(w,v, cap):
n = len(w)
m = [0]*(cap+1)
for i in range(n):
for j in range(cap, w[i]-1,-1):
m[j] = max(m[j], m[j-w[i]] + v[i])
return m[cap]
print(knap1(wt, val, 67))
print(knap2(wt, val, 67))
>>1270
>>1270
表方法更易于解释和调试,这就是为什么算法说明通常显示这种方式
注意,对于0-1背包问题,我们必须排除重复使用物品两次的可能性。所以在外循环的每一步,我们都使用当前项更新以前的最佳结果
但是我们只使用表的最后一行(查看索引i
和i-1
),因此我们可以仅使用当前行和最后一行将表大小减小到2 x容量
此外,我们可以使用一维数组的方法,应用一个技巧——为了避免重用项,我们可以执行反向遍历
下面的Python代码使用来自wiki页面的数据,并显示了表和线性数组实现
wt = [23,26,20,18,32,27,29,26,30,27]
val = [505,352,458,220,354,414,498,545,473,543]
def knap1(w,v, cap):
n = len(w)
m = [[0]*(cap+1) for _ in range(n)]
for i in range(n):
for j in range(cap + 1):
if w[i] > j:
m[i][j] = m[i-1][j]
else:
m[i][j] = max(m[i-1][j], m[i-1][j-w[i]] + v[i])
return m[n-1][cap]
def knap2(w,v, cap):
n = len(w)
m = [0]*(cap+1)
for i in range(n):
for j in range(cap, w[i]-1,-1):
m[j] = max(m[j], m[j-w[i]] + v[i])
return m[cap]
print(knap1(wt, val, 67))
print(knap2(wt, val, 67))
>>1270
>>1270
@对不起,我的问题是最后一句话,我只漏掉了问号here@EricPostpischil很抱歉,我的问题是最后一句话,我只漏掉了问号。很抱歉,如果我用2D表格来解无界背包,我会采用同样的解吗?我不知道为什么,但令人惊讶的是,你的两个算法给出了相同的结果,在什么情况下会发生?对于无界背包,你需要修改表算法-例如,选择最大值不仅使用m[I-1][j-w[I]+v[I]
单元格,而且使用m[I-1][j-2*w[I]+2*v[I]
等等,最多使用j/w[I]
项目。算法越复杂,速度越慢,一维算法就越好。我的两个实现给出了相同的结果,因为它们本质上代表了相同的解决方案<代码>项目0的最佳结果..i=>使用项目i+1更新,选择永久重量最大值(m[j],m[j-w[i]]+v[i])
因此我很抱歉,但是如果我应用2D表格来解决无界背包问题,我会采用相同的解决方案吗?我不知道为什么,但令人惊讶的是,你的两个算法给出了相同的结果,在什么情况下会发生?对于无界背包,你需要修改表算法-例如,选择最大值不仅使用m[I-1][j-w[I]+v[I]
单元格,而且使用m[I-1][j-2*w[I]+2*v[I]
等等,最多使用j/w[I]
项目。算法越复杂,速度越慢,一维算法就越好。我的两个实现给出了相同的结果,因为它们本质上代表了相同的解决方案<代码>项目0的最佳结果..i=>使用项目i+1更新,选择永久最大重量(m[j],m[j-w[i]]+v[i])
等等