ACM_01背包2
Posted 霜雪千年
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM_01背包2相关的知识,希望对你有一定的参考价值。
背包4
Time Limit: 2000/1000ms (Java/Others)
Problem Description:
有n个重量和价值分别为Wi,Vi的物品,现从这些物品中挑选出总量不超过W的物品,求所有方案中价值总和的最大值。
Input:
输入包含多组测试用例,每一例的开头为两位整数 n、W;接下来有 n 行,每一行有两位整数 Wi、Vi 其中: 1<=n<=100 1<=W<=1000,000,000(10^9) 1<=Wi<=10,000,000(10^7) 1<=Vi<=100。
Output:
输出为一行,即所有方案中价值总和的最大值。
Sample Input:
4 5 2 3 1 2 3 4 2 2 4 10000000 2 3 2 2 3 3 1 2
Sample Output:
7 10
解题思路:相比01背包之前的问题,只是修改了限制条件的大小,此前求解这一问题的时间复杂度是O(nW),但是对于这一问题,W最大为10^9,显然使用之前的方法会超时。但是可以发现,相比较重量而言,价值的范围比较小,因此换种角度可以解决此题。之前的方法中,dp[i]是求解当前重量i不超过总重量W下的最大价值,而这次的dp[i][j]表示从前i个物品中挑选价值总和为j(从0开始枚举)时总重量的最小值(不存在时就是一个充分大的INF)。因此循环下来最后从dp[n][j]中找到比W小的最大总重量(比之前的dp[n][j-1]还小)的j即为最大价值。
状态转移方程:dp[i+1][j]=dp[i][j],(j<v[i]);dp[i+1][j]=min(dp[i][j],dp[i][j-v[i]]+w[i])。(j>=v[i])
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAX_n 100 4 #define MAX_v 100 5 const int INF = 0x3f3f3f3f; 6 int w[MAX_n+1],v[MAX_n+1],dp[MAX_n+1][MAX_n*MAX_v+1]; 7 int main() 8 { 9 int n,W; 10 while(cin>>n>>W){ 11 fill(dp[0],dp[0]+MAX_n*MAX_v+1,INF); 12 dp[0][0]=0; 13 for(int i=0;i<n;++i) 14 cin>>w[i]>>v[i]; 15 for(int i=0;i<n;++i){ 16 for(int j=0;j<=MAX_n*MAX_v;++j){ 17 if(j<v[i])dp[i+1][j]=dp[i][j]; 18 else dp[i+1][j]=min(dp[i][j],dp[i][j-v[i]]+w[i]); 19 } 20 } 21 int res=0; 22 for(int j=0;j<=MAX_n*MAX_v;++j) 23 if(dp[n][j]<=W)res=j;//res表示最大价值 24 cout<<res<<endl; 25 } 26 return 0; 27 }
以上是关于ACM_01背包2的主要内容,如果未能解决你的问题,请参考以下文章