一维dp数组(滚动数组)
4.1使用二维数组,递推公式为 dp[i][j] = max(dp[i - 1][j] , dp[i - 1][j -weight[i]]+value[i]);
如果将dp[i - 1]所在层拷贝到dp[i]上,表达式转化为dp[i][j] = max(dp[i][j],dp[i][j-weight[i]] + value[i]);
(滚动数组)
满足上述条件的,即上一层可以重复利用,可以直接用一维数组来实现。
1.dp[i][j]含义是,从小标为0-i 的物品中任意取,放进容量为j的背包,价值总和最大多少
2.递推公式
dp[j]可以通过dp[j - weight[i]]推导,dp[j - weight[i]]表示容量为j - weight[i]的背包所背的最大价值。
dp[j - weight[i] + value[i]]表示容量为j - 物品i重量的背包加上物品i的价值。(即dp[j])
dp[j] = max(dp[j],dp[j - weight[i]]+value[i]);
//放或不放物品i,取价值最大的
3.初始化
结合定义,dp[0]=0;背包容量为0,价值为0
其他的,dp数组推导中取最大的,为避免结果被较大的初始值覆盖掉,应当将初始值设置为尽量小同时又要为非负数,不影响结果,全部初始化为0.
4.遍历顺序
//二维数组遍历是是从左上到右下,因此采取正序遍历
//这里倒序遍历是为了保证物品i只被放入1次
for(int i = 0; i < weight.size(); i++){
for(int j = bagWeight; j >= weight[i]; j--){ //背包遍历,从大到小
dp[j] = max(dp[j],dp[j - weight[i]] + value[i]);
}
}
void test_1_wei_bag_problem(){
vector<int>weight = {1,3,4};
vector<int>value = {15,20,30};
int bagWeight = 4;
//初始化
vector<int>dp(bagWeight + 1,0);
for(int i = 0;i < weigth.size(); i++){
for(int j = bagWeigt; j <= weight[i];j--){
dp[j] = max(dp[j], dp[j - weight[i]]+value[i]);
}
}
cout << dp[bagWeight]<<endl;
}