01背包2

有n个重量和价值分别为wi,vi的物品。从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值。

限制条件1<=n<=100,1<=wi<=10000000,1<=vi<=100,1<=W<=1000000000

 

和最初的01背包相比,只是修改了限制条件的大小。此前的复杂度是O(nW),对于这里就不可行了。

相比较重量而言,价值的范围比较小,试着改变dp的对象。

此前针对不同的重量限制计算最大的价值,现在针对不同的价值计算最小的重量。

 

定义dp[i+1][j]为从前i个物品中挑选出价值总和为j时总重量的最小值(不存在即为INF)

dp[0][0]=0

dp[0][j]=INF

易得递推关系式为dp[i+1][j]=min(dp[i][j],dp[i][j-v[i]]+w[i])

答案就是dp[n][j]中令dp[n][j]<=W的最大j

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<memory.h>
 4 #define INF 100000000
 5 using namespace std;
 6 const int max_n=101;
 7 int w[max_n+1];
 8 int v[max_n+1];
 9 int n,r;
10 long long W;
11 long long total=0;
12 int main()
13 {
14     cin>>n;
15     for(int i=0;i<n;i++)
16     {
17         cin>>w[i]>>v[i];
18         total+=v[i];
19     }
20     cin>>W;
21     long long dp[n+1][total+1];
22     fill(dp[0],dp[0]+total+1,INF);
23     dp[0][0]=0;
24     for(int i=0;i<n;i++)
25     {
26         for(int j=0;j<=total;j++)
27         {
28             if(j<v[i])
29             {
30                 dp[i+1][j]=dp[i][j];
31             }
32             else
33             {
34                 dp[i+1][j]=min(dp[i][j],dp[i][j-v[i]]+w[i]);
35             }
36         }
37     }
38     int res;
39     for(int i=0;i<=total;i++)
40     {
41         if(dp[n][i]<=W) res=i;
42     }
43     cout<<res<<endl;
44     return 0;
45 }
View Code

 

posted @ 2017-02-22 16:59  docyard  阅读(254)  评论(0编辑  收藏  举报