01背包是指,对于任意一个物品,它只能有两种状态:拿,或者不拿。就是说一个背包的容量是V,有n件物品,每个物品有着不同的重量和不同的价值,问如何放置可以使得背包的价值最大。
完全背包是指,对于任意一个物品,它都有无限多的数量。就是说一个背包的容量是V,有n件物品,每个物品有着不同的重量和不同的价值,每个物品都可以无限拿取,问如何放置可以使得背包的价值最大。
两种背包核心思想的差异:
首先想想为什么01中要按照v=V..0的逆序来循环。这是因为要保证第i次循环中的状态f[i][v]是由状态f[i-1][v-c[i]]递推而来。换句话说,这正是为了保证每件物品只选一次,保证在考虑“选入第i件物品”这件策略时,依据的是一个绝无已经选入第i件物品的子结果f[i-1][v-c[i]]。 (01背包讲解) 而现在完全背包的特点恰是每种物品可选无限件,所以在考虑“加选一件第i种物品”这种策略时,却正需要一个可能已选入第i种物品的子结果f[i][v-c[i]],所以就可以并且必须采用v=0..V的顺序循环。
01背包核心代码:
for(int i=1;i<=n;i++)
for(int j=m;j>=w[i];j--)
dp[j] = max( dp[j-w[i]]+val[i], dp[j] );
完全背包核心代码:
for(int i=1;i<=n;i++)
for(int j=w[i];j<=m;j++) //顺序
dp[j]=max(dp[j-w[i]]+val[i], dp[j]);
- 注意完全背包所得的最大值不一定在dp[m]中,所以需要遍历dp数组来得到最大值