这个问题总是看了忘,忘了看,昨天笔试碰到又不会做了。今天把它写在博客里,时时温习。
1. 01背包
01背包问题描述:有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,每件物品数量只有一个,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
item 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
item 1 | 0 | 0 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
item 2 | 0 | 0 | 6 | 6 | 9 | 9 | 9 | 9 | 9 | 9 | 9 |
item 3 | 0 | 0 | 6 | 6 | 9 | 9 | 9 | 9 | 11 | 11 | 14 |
item 4 | 0 | 0 | 6 | 6 | 9 | 9 | 9 | 10 | 11 | 13 | 14 |
item 5 | 0 | 0 | 6 | 6 | 9 | 9 | 12 | 12 | 15 | 15 | 15 |
表格dp中行i表示可以放入的物品为0~i,列j表示背包的重量,故dp(i,j)表示当有一个重量为j的包,可以选择的物品是0~i,此时它的最大价值。
状态方程:
所以代码可以写为
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int w[6] = {0};
int v[6] = {0};
int dp[6][6] = {0};
int c;
int n = 5;
for (int i=1; i<=n; ++i)
cin>>w[i];
for (int i=1; i<=n; ++i)
cin>>v[i];
cin>>c;
for (int i=1; i<=n; ++i)
{
for (int j=1; j<=n; ++j)
{
if (j<w[i])
dp[i][j] = dp[i-1][j];
else
dp[i][j] = max(dp[i-1][j-w[i]]+v[i], dp[i-1][j]);
}
}
cout<<dp[n][c];
return 0;
}
2. 完全背包
将上题的条件,每个物品有一件改为有无数个。
状态方程改为: