在我为0/1背包和无界背包签出的所有DP解决方案中,解决方案方法总是这样定义的:
0/1背包:取第n项或不取第n项,使总价值最大化。例如,0/1背包
无界背包:将第n个物品视为最后挑选的物品,或(n-1)个物品视为最后挑选的物品,使总价值最大化。例如,无界背包
但无界背包也可以使用0/1背包的逻辑来解决,只需稍加调整。我的意思是,对于0/1背包,我们执行以下操作(使用第一个链接中的代码):
return max( val[n-1] + knapSack(W-wt[n-1], wt, val, n-1),
knapSack(W, wt, val, n-1)
);
请注意,在包含wt[n-1]的情况下,我们将数组的大小减少了1。这意味着wt[n-1]现已耗尽,因此不能再次使用。但如果在无界情况下,我们不将数组大小减少1(这意味着可以再次使用wt[n-1]),则以下稍微修改的递归关系可以正常工作:
return max( val[n-1] + knapSack(W-wt[n-1], wt, val, n),
knapSack(W, wt, val, n-1)
);
为什么这种无界背包的方法在任何地方都没有提到?实际上这里它特别指出,对于无界背包,我们不能使用与0/1背包相同的逻辑。该链接摘录:
Observation:
I can never exhaust any item because there are an unbounded supply of items.
Therefore:
The technique used in the 0,1 knapsack problem cannot be used.
但是我不能反驳我上面提到的解决方案是行不通的。这个想法来自硬币兑换问题,在这个问题中,假设硬币的供应量是无限的,你必须计算出改变给定数量的方法。
所以我的问题是为什么我在这里提出的方法从未用于无界背包,或者至少从未在任何地方提到过?有人能帮我证明或反驳这种方法吗?提前谢谢!
如果你在无界背包中使用这种方法,那么程序的空间复杂度将是O(n*W),如果你使用到处都给出的方法,那么它将是O(n W),其中n是项数,W是总重。
您不会在任何地方找到您提到的解决方案,因为您的解决方案不是动态编程方法。在您的代码中,它是重新评估动态编程中不应该发生的子案例。如果您愿意,您可以尝试此代码,与您的代码相同,但它遵循动态编程规则
def UnboundedKnapSack2(wt, val, n, capacity):
global dp
if dp[n][capacity] != -1:
return dp[n][capacity]
else:
if n == 0 or capacity <= 0:
dp[n][capacity] = 0
return dp[n][capacity]
elif wt[n - 1] <= capacity:
dp[n][capacity] = max(
val[n - 1] + UnboundedKnapSack(wt, val, n, capacity - wt[n - 1]),
UnboundedKnapSack(wt, val, n - 1, capacity),
)
return dp[n][capacity]
else:
dp[n][capacity] = UnboundedKnapSack(wt, val, n - 1, capacity)
return dp[n][capacity]
weight = [1, 3, 4, 5]
values = [10, 40, 50, 70]
capacity = 8
dp = [[-1 for i in range(capacity + 1)] for j in range(len(weight) + 1)]
print(UnboundedKnapSack2(weight, values, len(weight), capacity))
这不是您的问题的唯一解决方案,还有其他根本不使用递归的动态编程代码。
def UnboundedKnapSack3(wt, val, capacity):
n = len(wt)
dp = [[0 for i in range(capacity + 1)] for j in range(n + 1)]
for i in range(n + 1):
for j in range(capacity + 1):
if i == 0 or j == 0:
dp[i][j] = 0
elif j >= wt[i - 1]:
dp[i][j] = max(val[i - 1] + dp[i][j - wt[i - 1]], dp[i - 1][j])
else:
dp[i][j] = dp[i - 1][j]
return dp[-1][-1]
print(UnboundedKnapSack3([1, 3, 4, 5], [10, 40, 50, 70], 8))
使用您喜欢的方法,但确保不应重新计算重叠的子问题。
在每个递归调用中,函数都会遍历所有可用的权重,以查看是否可以包含它,如果可以,则其值将累积到当前递归调用的max\u val中。在调用结束时,如果我们能够获得一个值,那么它将返回一个标志,告诉我们找到了一个解决方案,并将maxSoFar设置为max\u值。
#include<bits/stdc++.h>
using namespace std;
// Returns the maximum value with knapsack of
// W capacity
int unboundedKnapsack(int W, int n, int val[], int wt[], int &maxValue)
{
// dp[i] is going to store maximum value
// with knapsack capacity i.
if( W == 0)
return true;
int maxSoFar = INT_MIN;
bool foundASeries = false;
for(int i = 0; i < n; i++)
{
if(W >= wt[i])
{
maxValue = 0;
if(unboundedKnapsack(W-wt[i], n, val, wt, maxValue))
{
foundASeries = true;
maxSoFar = max(maxSoFar, maxValue + val[i]);
}
}
}
maxValue = maxSoFar;
return foundASeries;
}
// Driver program
int main()
{
int W = 8;
int val[] = {10, 40, 50, 70};
int wt[] = {1, 3, 4, 5};
int maxValue = 0;
int n = sizeof(val)/sizeof(val[0]);
cout << unboundedKnapsack(W, n, val, wt, maxValue)<<endl;
cout<< "max value is "<<maxValue;
return 0;
}
我试图在Scala中使用递归来解决背包问题,但我的要求是显示选择哪些项目保存在背包中。表示背包大小。 我的代码如下: 如何知道选择哪些物品放在背包里?
我对这个问题有点困惑。作为算法帮助我找到最大的利润从袋。但是这个算法并没有告诉我我应该拿哪一个项目会让我的利润最大。例如 n=4项,背包的容量M=8,利润=[15,10,9,5],重量分别为w=[1,5,3,4],当我解决这个问题时,我得到最大的利润为29 这里是解决方案[http://www.mafy.lut.fi/study/DiscreteOpt/DYNKNAP.pdf] 但是我想知道我应该
我写了一个背包类,我用它来解决背包算法。这个类正在使用动态规划算法来解决这个问题。 我在代码中实现了一些优化,因此我使用线性O(W)空间来找到最大值,但当我试图找到见证时,我仍然需要O(nW)空间来保持布尔表。 有人能告诉我,是否有可能找到背包容量最大、空间较小、复杂度与O(nW)相同的证据,这里W是背包容量。 如果您认为代码中可能还有更多优化,请也告诉他们。
本文向大家介绍C中的0-1背包问题?,包括了C中的0-1背包问题?的使用技巧和注意事项,需要的朋友参考一下 背包是袋子。背包问题是根据物品的值将物品放入袋中的。目的是使袋子内的值最大化。在0-1背包中,您既可以放置物品也可以将其丢弃,没有将物品的某些部分放入背包的概念。 样本问题 重量分布 最大值为65,因此我们将项目2和3放入背包。 0-1背包问题计划 输出结果
本文向大家介绍解决0-1背包问题的C ++程序,包括了解决0-1背包问题的C ++程序的使用技巧和注意事项,需要的朋友参考一下 在0-1背包问题中,给出了一组项目,每个项目都有一个权重和一个值。我们需要确定要包含在集合中的每个项目的数量,以使总重量小于或等于给定的限制,并且总值尽可能大。 输入项 输出结果 算法 范例程式码 输出结果
我正在为即将到来的测试复习,想知道是否有人能重述问题的b部分。这是从分发的复习表中得到的文本,但我不确定b部分到底在问什么。我更直截了当地猜测“生成一个不到0/1背包问题最优值1%的解”是什么意思。 b)[10pts]举了一个有两个对象的例子,说明对分数背包问题使用的相同的贪婪方法(略加修改,如果贪婪方法选择的最后一个对象不适合,则忽略它)得到的解不到0/1背包问题最优解的1%。