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的主要内容,如果未能解决你的问题,请参考以下文章

uestc1218_变形01背包

XDOJ_1172_01背包

HDU_1864_01背包

XDOJ_1073_01背包

ACM:动态规划,01背包问题

ACM_完全背包