//二维dp数组01背包
/*
1:确定dp数组以及下标的含义,对于背包问题,有一种写法,是使用二维dp数组,集dp[i][j]
表示的含义是以i为结尾的物品,放进容量为j的背包,价值综合最大是多少
2:确定递推公式
对于每个物品,都有拿或者不拿两个状态
(1)如果不拿,dp[i][j]=dp[i-1][j]
(2)如果拿:dp[i][j]=dp[i-1][j-weight[i]+value[i]
所以递推公式:dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]+value[i])
3:dp数组的初始化问题:
关于dp数组的初始化,一定要和dp数组的定义吻合,因此;如果背包容量为0的话,dp[i][0]=0;即dp数组的第一列为0
状态转移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]+value[i])可以判断i
是由i-1推出来的,那么i=0的时候就一定要初始化
即dp[0][j];存放编号为0的物品的时候,各个容量的背包所能存放的最大价值
这里要用倒序遍历(为了保证每个物品只被放入一次)
for(int j=barweight;j>=weight[0];j--)
{
dp[0][j]=dp[0][j-weight[0]]+value[0];
}
正序遍历代码
for(int j=weight[0];j<=bagweight;j++)
{
dp[0][j]=dp[0][j-weight[0]]+value[0];
}
4:确定遍历顺序:
dp数组有两个维度:物品与背包重量
在二维数组中先白能力物品或者是背包容量都可以
1.先遍历物品的个数
for(int i=1;i<weight.size();i++)
{
for(int j=0;j<bagweight;j++
{
if(j<weight[i]] dp[i][j]=dp[i-1][j];
else
{
dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])
}
}
}
,相当于拿每一个物体分别放入不同容量的背包中
2.先遍历背包容量
for(int j=0;j<bagwieght;j++)
{
for(int i=1;i<weight.size();i++)
{
if(j<weight[i])dp[i][j]=dp[i-1][j];
else
{
dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);
}
}
}
*/
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void test_2_wei_bag_problem() {
vector<int> weight = { 1,3,4 };
vector<int> value = { 15,20,30 };
int bagweight = 4;
vector<vector<int>> dp(weight.size() + 1, vector<int>(bagweight + 1,0));
for (int j = bagweight; j >= weight[0]; j--)
{
dp[0][j] = dp[0][j - weight[0]] + value[0];
}
for (int i = 1; i < weight.size(); i++)
{
for (int j = 0; j < bagweight; j++)
{
if (j < weight[i]) dp[i][j] = dp[i - 1][j];
else
{
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
}
}
}
cout << dp[weight.size() - 1][bagweight] << endl;
};
int main()
{
test_2_wei_bag_problem();
return 0;
}
结果: