1. 01背包
背包就是一种动态规划,而动态规划最重要的就是动态转移方程。01背包是背包中最简单的一种,它能解决什么问题呢?
看洛谷的: P1048
简化题意得到:
输入T和M,表示背包容量和物品数量,接下来M行,输入w[i]和 v[i]表示物品的大小和价值,输出背包能装下的最大价值。
-
30 % 的数据 M≤10
-
100 % 的数据 M≤100
首先,我们创建一个dp[N][N]的数组,表示一张表格
一开始都赋值成0,竖维枚举物品编号,横维枚举背包大小,dp[i][j]表示当背包容量为jj时,只选前i个物品时的最大值。
我们知道,01背包分为选与不选两种情况,当背包容量+1时,就会分为两种情况:
-
不选:
那就与只选前i−1个物品一样,只是容量增加了1,所以dp[i][j]的最大价值就是从dp[i−1][j]那里继承下来的,所以我们得到:
当不选第i−1个物品时,
dp[i][j]=dp[i-1][j]
-
选:
如果你想选第i−1个物品,那你就得看看这时候背包的剩余容量够不够装下它,得到:
if(j>=w[i])
如果成立,此时,你就可以选他了,不过,你的背包容量也变成了j−w[i],但你也可以获得其相应的价值v[i]v[i],而你的背包为j−w[i]的容量时相应的价值就是dp[i−1][j−w[i]],再加上第i个的价值v[i],所以我们得到:
当选第i−1i−1个物品时,
dp[i][j]=dp[i−1][j−w[i]]+v[i]
然后我们取最大值:
dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+t[i]);
如果不成立,那我们别无他法,只能不选了,得到:
else
dp[i][j]=dp[i-1][j];
完整动态转移方程为:
if(j>=w[i]) dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+t[i]);
else dp[i][j]=dp[i-1][j];
核心代码为:
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(j>=w[i]) dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
else dp[i][j]=dp[i-1][j];
}
}
大家可以尝试完成例题: