背包2
Time Limit: 2000/1000ms (Java/Others)
Problem Description:
有n个重量和价值分别为Wi,Vi的物品,现从这些物品中挑选出总量刚好为 W 的物品,求所有方案中价值总和的最大值。
Input:
输入包含多组测试用例,每一例的开头为两位整数 n、W(1<=n<=10000,1<=W<=1000),接下来有 n 行,每一行有两位整数 Wi、Vi(1<=Wi<=10000,1<=Vi<=100)。
Output:
输出为一行,即所有方案中价值总和的最大值。若不存在刚好填满的情况,输出“-1”。
Sample Input:
3 4 1 2 2 5 2 1 3 4 1 2 2 5 5 1
Sample Output:
6 -1
解题思路:这是01背包的修改版。结合题目,若不存在刚好填满的情况为-1,我们可以把dp数组元素全部初始化为-1,这样直接输出dp[W]就可以知道从这些物品中挑选出总量刚好为W时,其价值总和是不是也达到最大,并且不是-1时才可以使用状态转移方程。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int w[10005],v[10005],dp[10005]; 4 int main() 5 { 6 int n,W; 7 while(cin>>n>>W){ 8 memset(dp,-1,sizeof(dp)); //全部初始化为-1 9 dp[0]=0;//默认初始化为0 10 for(int i=0;i<n;++i) 11 cin>>w[i]>>v[i]; 12 for(int i=0;i<n;++i){ 13 for(int j=W;j>=w[i];--j){ 14 if(dp[j-w[i]]!=-1) //如果不是-1的才可以进行比较取舍 15 dp[j]=max(dp[j],dp[j-w[i]]+v[i]); 16 } 17 } 18 cout<<dp[W]<<endl; //直接输出总量为W时的价值 19 } 20 return 0; 21 }