给定一组有固定价值和固定重量的物品,以及一个已知最大承重量的背包,求在不超过背包最大承重量的前提下,能放进背包里面的物品的最大总价值。要求物品不能分割开来。
01代表装或不装。
问题的难点在于哪里呢?
首先最终目的是总价值最大,而承重量则是一个限制条件。一般而言。对于背包问题的贪心算法是计算性价比后优先放入性价比高的物品,由于贪心类问题中允许把物体分开后放入背包,其实并不难。
而在动态分配问题中呢?
物体不能被分割的情况下,如何能做到价值的最大化变成了难点,不一定性价比最高的最后获得的总价值最高,因为承重量的限制可能导致你在放入性价比最高的物体后,就无法继续放入了,反而导致总价值不高。
举个例子:
限重 5 kg
质量: 1 ,2 , 4
价值:10,16,30
最大价值为40
如果按性价比排名放入只能拿到26了。
因此怎么去考虑这类问题呢?
就拿第一个物品来说
总的问题可以分解为两个子问题:
①装第一个物品 我剩余的空间能装多大价值的物品
②不装第一个物品 我剩余的空间能装多大价值的物品
类推到第i个物品:
if(c[i] > j)
dp[i][j] = dp[i - 1][j];//情况②
else
dp[i][j] = max(p[i - 1][j], p[i - 1][j - w[i]] + v[i]);//①
我慢慢分析这一行代码。
p[i][j]代表的是在限重为j的情况下,前n个物品能获得的最大价值。
max是系统函数max,返回两个值中的较大值。
是哪两个值呢?
p[ i-1 ][ j ]和 j - w[i] ] + v[ i ] ,分别对应两种子问题。
p[ i-1 ][ j ]对应的是上面的②,即在不拿第i个物品,在限重为j的情况下,前i-1个物品能取得的最大价值
j - w[i] ] + v[ i ] 对应①,即拿了第i个物品,在限重为j-w[i](第i个物品确定拿,剩余空间减小了)的情况下,前i-1个物品能拿到的最大价值加上第i个物品的价值
for(int i = 1; i <= N; i++) //i对应第i个物品,i的循环放外面,V[i][] 对应数据由V[i-1][] 决定
{
for(int j = 1; j <= M; j++) //j对应当前背包能承受重量为j
{
if(j >= [i])
{
p[i][j] = max(p[i - 1][j], p[i - 1][j - w[i]] + v[i]);
}
else
{
p[i][j] = p[i - 1][j];
}
}
}