Bone Collector HDU - 2602(题解)

原题

原题链接

题目大意

题目大概是讲有一个背包(给容量),然后又一排骨头,骨头有体积和价值,你要用这个背包装这些骨头,使骨头的价值之和最大化,并输出该值.

题目分析

标准的01背包模板.这里讲一下01背包的更新过程,首先设一个dp数组(一维),dp[i]表示用i格容量最多能装多少价值的东西,数组初始化为-1(dp[0]=0).要更新这个dp数组,先用一个外循环(i=1→n)来遍历每个物品,然后内循环(j=k→w[i])(k是背包容量)从背包容量大小开始往前更新,(这里w[i]是每个物品的体积,v[i]是每个物品的价值)也就是if(dp[j-w[i]]更新过,这里是dp[j-w[i]]!=-1) dp[j]=max(dp[j],dp[j-w[i]]+v[i])(注意一下j-w[i]不要越界),这里从后往前更新的原因是这样子能保证每个物品只装一次,这也是和完全背包的区别,想一下如果从前往后更新的话,这里假设i=1,w[1]=1,v[1]=1,外循环扫第一遍时即i=1,如果从后往前更新,则有if(dp[j]!=-1) dp[j+w[i]]=max(dp[j+w[i]],dp[j]+v[i])(同样注意i+w[i]不要越界),当内循环j=0时,更新dp[1]=1,然后j=2,更新dp[2]=2,这里就开始错了,因为这时候dp[2]已经装了两个第1个物品了.

代码

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <string>
 8 #include <utility>
 9 #include <queue>
10 #include <stack>
11 const int INF=0x3f3f3f3f;
12 using namespace std;
13 
14 const int Max=1000;
15 int dp[Max+1];
16 int w[Max+1],v[Max+1];
17 
18 int main()
19 {
20     int t;
21     cin>>t; 
22     while(t--)
23     {
24         int n,k;
25         memset(w,0,sizeof(w));
26         memset(v,0,sizeof(v));
27         cin>>n>>k;
28         for(int i=1;i<=n;i++)
29         cin>>v[i];
30         for(int i=1;i<=n;i++)
31         cin>>w[i];
32         memset(dp,-1,sizeof(dp));
33         dp[0]=0;
34         for(int i=1;i<=n;i++)
35         for(int j=k;j>=w[i];j--) //j>=w[i]保证不越界 
36         if(dp[j-w[i]]!=-1) dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
37         int ans=0;
38         for(int i=1;i<=k;i++) //扫一遍dp数组里的最大值 
39         if(ans<dp[i]) ans=dp[i];
40         cout<<ans<<endl;
41     }
42     return 0;
43 }

 

posted @ 2019-02-25 17:02  VBL  阅读(138)  评论(0编辑  收藏  举报