01背包
01背包考虑的其实就是当前物品要或不要的这么一个问题。以采药一题为例,二维情况下,f[i][c]表示前i件物品放入一个容量为c的背包可以获得的最大价值。那么状态转移方程就是:
f[i][c]=max(f[i-1][c],f[i-1][c-v[i]]+w[i]);
核心代码如下:
for(int i=1;i<=m;i++)
for(int j=t;j>=0;j--)
{
dp[i][j]=dp[i-1][j];
if(j>=w[i]) dp[i][j]=max(dp[i-1][j-w[i]]+val[i],dp[i-1][j]);
}
这样,这道题就完成了,但是但是但是,人类的智慧是无穷的,这道题,我们可以滚掉一维,但是需要反着枚举,因为我们在求f[c]的时候,必须保证f[c-v[i]]还是第i-1阶的最优值,不能让他是更新后的状态。
核心代码如下:
for(int i=1;i<=m;i++)
for(int j=t;j>=0;j--)
if(j>=w[i]) dp[j]=max(dp[j-w[i]]+val[i], dp[j]);
(注:当发现当前层只与前一层有关时,都可以考虑将二维简化为一维)
完全背包问题
这类问题其实与01背包非常类似,只是物品有无限件而已。
多重背包问题
做题思想:二进制拆分。即把数字拆成二的整次幂相加的形式,以指数为变量进行枚举。
板子题:逃亡的准备