问题描述
给定N个物品,每个物品有一个重量W和一个价值V.你有一个能装M重量的背包.问怎么装使得所装价值最大.每个物品只有一个.
输入格式
输入的第一行包含两个整数n, m,分别表示物品的个数和背包能装重量。 以后N行每行两个数Wi和Vi,表示物品的重量和价值
输出格式
输出1行,包含一个整数,表示最大价值。
样例输入
3 5 2 3 3 5 4 7
样例输出
8
数据规模和约定
1<=N<=200,M<=5000. 看到这个问题,可能会想到贪心算法,但是贪心其实是不对的。例如最少硬币找零问题,要用动态规划。
动态规划思想就是解决子问题并记录子问题的解,这样就不用重复解决子问题了。
动态规划先找出子问题,我们可以这样考虑:在物品比较少,背包容量比较小时怎么解决?
- 用一个数组wv[i][j]表示,在只有i个物品,容量为j的情况下背包问题的最优解,
- 那么当物品种类变大为i+1时,最优解是什么?第i+1个物品可以选择放进背包或者不放进背包(这也就是0和1),
- 假设放进背包(前提是放得下),那么wv[i+1][j]=wv[i][j-weight[i+1]]+value[i+1];如果不放进背包,那么wv[i+1][j]=wv[i][j]。 这就得出了状态转移方程: wv[i+1][j]=max(f[i][j],wv[i][j-weight[i+1]]+value[i+1])。
#include<iostream>
using namespace std;
int w[205];
int v[205];
int wv[205][5005]={0};//全局变量,初始化为0
int main()
{
int i,j,n,m;
cin>>n;
cin>>m;
for(i=1;i<=n;i++)
{
cin>>w[i];
cin>>v[i];
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(w[i]<=j)
wv[i][j]=max(wv[i-1][j],v[i]+wv[i-1][j-w[i]]);
else
wv[i][j]=wv[i-1][j];
}
cout<<wv[n][m]<<endl;
return 0;
}