问题如下
问题描述:
给定n个重量为w[i],价值为c[i]的物品(i=1,2,…,n),以及一个重量为v的背包,问如何选取物品放入背包,使得背包内物品的总价值最大,其中每种物品只有1件。
输入样例:(第一行是背包重量上限以及物品数量,第二、三、四、五行是物品的重量和价值)
10 4
7 42
3 12
4 40
5 25
输出样例:(能够放入背包的物品最大价值)
65 (即最后两个物品)
思路:
dp[i][j]
表示前i件物品恰好装入容量为j的背包所能获得的最大价值,则如果
1.不放第i件物品,则 dp[i][j] = dp[i-1][j]
2.放第i件物品,那么问题转化为前i – 1件物品恰好装入容量j – w[i]的背包中所能获得的最大价值 dp[i-1][j-w[i]] + c[i](加c[i]表示已经确定i会放入)
递推方程dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+c[i]);
部分代码如下:
for(int i = 1; i <= n; i++) { //对n个物品选择
for(int j = 1; j <= v; j++) //穷尽背包空间
if(j - w[i] >= 0) //还有空间能放i
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + c[i]);
else
dp[i][j] = dp[i-1][j];
}
一维:
for(int i = 1; i <= n; i++) {
for(int j = v; j >= w[i]; j--)
dp[v] = max(dp[v], dp[v-w[i]] + c[i]);
}
完整代码:
#include<bits/stdc++.h>
using namespace std;
int n, v, Max; //n为物品数量,v为背包空间,Max为最大价值
int main()
{
cin >> v >> n;
int c[n + 1], w[n + 1];
for(int i = 1; i <= n; i++) //从下标1开始
{
cin >> w[i] >> c[i];
}
int dp[n + 1][v + 1];
memset(dp, 0, sizeof(dp)); //dp数组初始化为0
for(int i = 1; i <= n; i++) //对n个物品选择
{
for(int j = 1; j <= v; j++) //穷尽背包空间
{
if(j - w[i] >= 0) //还有空间能放i
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + c[i]);
else
dp[i][j] = dp[i - 1][j];
if(dp[i][j] > Max) //更新Max
Max = dp[i][j];
}
}
cout << Max;
}