一、引言
01背包,0与1分别代表一件物品不选与选,不选或选就提供了两种路,就可以用动态规划来解决。
二、分析
举一个采药原题的输入输出样例的例子,有70容量的背包,有3件物品,分别是:需要71容量、100价值的物品A,需要69容量、1价值的物品B,需要1容量、2价值的物品C
这样总价值最大的是装物品B和物品C,总价值是3
则我们可以列一个DP数组用来存储对应情况的最优放法,DP[i][j]表示在前 i 种物品中用 j 容量最多可以装价值多少的东西
首先用一个双层循环,i 用于循环物品, j 用于循环背包容量,当 j < v[i] 时(当这件物品装不下时,那肯定不选这件物品,所以就等于不选这件物品时的最大价值,即dp[ i ][ j ] = dp[ i - 1][ j ] )
核心代码如下:
dp[i][j] = dp[i-1][j]; //不选这件物品
if(j >= v[i]){ //如果背包容量可以装下这个物品
dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]] + w[i]); //就从选这个物品和不选这个物品中挑一个价值更大的
}
三、完整代码
#include<iostream>
using namespace std;
const int N = 1e3 + 5;
int dp[N][N], w[N], v[N]; //分别是dp数组、价格数组和容量数组
int m, n;
int main(){
scanf("%d%d", &m, &n); //m表示物品数量,n表示背包总容量
for(int i = 1; i <= m; i++){ //从1开始存,避免减一超范围
scanf("%d%d", &w[i], &v[i]); //每件物品的价格与容量
}
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
dp[i][j] = dp[i-1][j]; //不选这件物品
if(j >= v[i]){ //如果背包容量可以装下这个物品
dp[i][j] = max(dp[i-1][j], dp[i-1][j-v[i]] + w[i]); //就从选这个物品和不选这个物品中挑一个价值更大的
}
}
}
printf("%d", dp[m][n]);
}