输入
第1行,2个整数,N和W中间用空格隔开。N为物品的数量,W为背包的容量。(1 <= N <= 100,1 <= W <= 10000) 第2 - N + 1行,每行2个整数,Wi和Pi,分别是物品的体积和物品的价值。(1 <= Wi, Pi <= 10000)
输出
输出可以容纳的最大价值。
输入示例
3 6 2 5 3 8 4 9
输出示例
14这个题直接说一下递推式的确定,51nod 上面这样写到令f(i,j)表示选决定了前i件物品,重量恰好为j的时候能获得的最大价值。对f(i,j)如果我们不选取第i件物品,则显然。然后我当初是这样理解的,既然能去第i件物品为什么不取。其实这句话这样理解,就是f(i,j)表示,物品一共有i件,这个时候背包的容量是j,所以对于递推式的确定,就是说如果不取这个第i件物品,那么这个时候的背包的容量j不会变,这时就判断第(i-1)件物品取还是不取,所以这个时候f(i, j) = f(i – 1,j),如果取了第i件物品,这个时候背包容量就是j-wi的重量加上i的价值,判断哪个总收益最高,所以总的递推式是f(i,j) = max(f(i – 1, j) , f(i-1,j - wi) + vi)。然后这个剩下就是用dp[n][w] 了,题解用i从1循环到n,j从0到w,这个时候就加了一个判断,就是如果这个时候第i件物品的重量大于背包直接承受的重量 ,则f(i, j) = f(i – 1,j)。所以源代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int dp[105][10010];
int wi[10010],pi[10010];
int main()
{
int i,j;
int n,w;
scanf("%d%d",&n,&w);
for(i=1;i<=n;i++)
{
scanf("%d%d",&wi[i],&pi[i]);
}
for(i=1;i<=n;i++)
{
for(j=0;j<=w;j++)
{
if(j<wi[i]){
dp[i][j]=dp[i-1][j];
}
else
{
dp[i][j]=max(dp[i-1][j],dp[i-1][j-wi[i]]+pi[i]);
}
}
}
printf("%d\n",dp[n][w]);
return 0;
}
优化代码:
// >File Name: 0-1背包问题.cpp
// > Author: Webwei
#include<iostream>
#include<algorithm>
#include<cstring>
#define MAX 10010
using namespace std;
int dp[100010];
int main()
{
int n,C,v,w;
cin>>n>>C;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
{
cin>>v>>w;
for(int j=C;j>=v;j--)
{
if(dp[j]<dp[j-v]+w) dp[j]=dp[j-v]+w;
}
}
cout<<dp[C]<<endl;
return 0;
}