01背包: n种物品,每种物品只有一个
所有背包问题的基础233
(区别于完全背包:n种物品,每种物品有无限个,多重背包:n种物品,每种物品的个数各不相同)
每种物品有自己的重量和自己的价值,有一个最多只能放重量为m的背包,问此背包最多能装价值为多少的物品
举个栗子:
重量 | 价值 | |
物品0 | 2 | 15 |
物品1 | 3 | 20 |
物品2 | 4 | 30 |
背包最大重量为4
定义一个二维数组dp[i][j];
这个dp数组的含义,其实是:
[0,i]下标从0-i之间的物品
也就是上面的表格中的物品编号0,1,2任取一个放进容量为j的背包里
我们的递推都是要围绕着这个dp数组的含义来写
接下来来确定递推公式
当前背包的状态其实取决于选择放或不放当前的这个物品i,放物品i是一个状态,不放物品i是一另个状态
我们假设不放物品i,那么是什么状态呢?
数组dp[i][j]中,不放物品i容量为j,*它所能装的最大价值是dp[i-1][j]
(为什么是i-1呢?就是0到i-1之间物品任取,就是相当于不放物品i)
如果放物品i呢?
此时的最大价值应该是这个背包容量减去物品i的容量之后所能放的最大价值,再加上物品i的价值
*它所能装的最大价值是dp[i-1][j-weight[i]]+value[i]
(为什么这里放了物品i还是[i-1]呢?后面要加上value[i],但是加之前还没放)
那么我们要找最大值,那自然是比较放与不放两种状态哪一种的价值最高
那么,我们的递推公式dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])
我们看一下最后的模板
for( ) { //遍历物品(两层for循环可以对调顺序)
for( ) { //遍历背包
dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]); //递推公式
}
}