动态规划学习四 | 0-1背包问题
问题描述
有n 个物品,它们有各自的重量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?
举例
number=4,capacity=8
i | 1 | 2 | 3 | 4 |
---|---|---|---|---|
w(体积) | 2 | 3 | 4 | 5 |
v(价值) | 3 | 4 | 5 | 6 |
过程
-
这是最基本的背包问题.
-
特点: 每种物体仅有一件. 可以选择放或者不放.
-
用子问题定义状态: 即
f[i][j]
表示前i件物体放入一个容量为j的背包可以获得的最大价值. -
其状态转移方程为:
-
tab[i][j] = max( tab[i-1][j-wight[i]]+value[i],tab[i-1][j])
tab[i-1][j]
表示不放 i 物体的总价值tab[i-1][j-wight[i]]+value[i]
表示放了i物体的总价值
代码实现
int FindMax(vector<int> weight, vector<int> value, int capacity) {
int n = weight.size();
vector < vector<int>> dp(n + 1, vector<int>(capacity + 1, 0));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= capacity; j++) {
// 背包装不进东西
if (j < weight[i - 1]) {
dp[i][j] = dp[i - 1][j];
} else {
// 背包能装进东西
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i - 1]] + value[i - 1]);
}
}
}
return dp[n][capacity];
}
寻找装了哪些东西
void FindWhat(int i,int j)//寻找解的组成方式
{
if(i>=0)
{
if(V[i][j]==V[i-1][j])//相等说明没装
{
item[i]=0;//全局变量,标记未被选中
FindWhat(i-1,j);
}
else if( j-w[i]>=0 && V[i][j]==V[i-1][j-w[i]]+v[i] )
{
item[i]=1;//标记已被选中
FindWhat(i-1,j-w[i]);//回到装包之前的位置
}
}
}