1. 程式人生 > >HDU 2602 Bone Collector(01揹包)

HDU 2602 Bone Collector(01揹包)

Bone Collector

  Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave … 
The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ? 

Input

  The first line contain a integer T , the number of cases. 
  Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.

Output

  One integer per line representing the maximum of the total value (this number will be less than 231).

Sample Input

1
5 10
1 2 3 4 5
5 4 3 2 1

Sample Output

14

解題思路:
  本題給出測試數量,每組測試給出骨骼數量n與揹包體積v,之後跟隨兩行,第一行為骨骼的價值,第二行為骨骼的體積。要求輸出揹包所能裝下骨骼的最大價值。

  本題是標準的0 1揹包問題。基本思路是動態規劃,令dp[ j ]表示揹包容量為j時能裝下骨骼的最大價值。

  對於第i塊骨骼,有拿或不拿兩種方案。

  1、拿第 i 塊骨骼,問題轉化為計算揹包容量為j - volume[ i ] 在前i - 1塊骨骼中取得最大價值問題d[ j ]的值為前i - 1塊骨骼中取得的最大價值 + 第i塊骨骼的價值。

  2、不拿第i塊骨骼,問題轉化為揹包容量為 j 時在前i - 1塊骨骼中取得最大價值問題,d[ j ]的值為前i - 1塊骨骼中取得的最大價值。

  可以寫出狀態轉移方程:dp[ j ] = max(dp[ j ], dp[ j - volume[ i ] ] + value[ i ])

  邊界為拿前0塊骨骼,最大價值為0,列舉所以骨骼,每次從最大揹包容量開始逆序列舉容量便可獲得答案。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e3+100;
 4 int value[maxn], volume[maxn];
 5 //value記錄骨骼價值volume記錄骨骼體積
 6 int dp[maxn];
 7 int main()
 8 {
 9     int t;  //測試數量
10     while(scanf("%d", &t) != EOF){
11         int n, v;   //n為骨骼數量 v揹包容量
12         while(t--){
13             scanf("%d%d", &n, &v);
14             for(int i = 1; i <= n; i++){
15                 scanf("%d", &value[i]); //輸入骨骼價值
16             }
17             for(int i = 1; i <= n; i++){
18                 scanf("%d", &volume[i]);    //輸入骨骼體積
19             }
20             memset(dp, 0, sizeof(dp));  //初始化邊界
21             for(int i = 0; i <= n; i++){    //列舉骨骼
22                 for(int j = v; j >= volume[i]; j--){  //逆序列舉體積  
23                     dp[j] = max(dp[j], dp[j - volume[i]] + value[i]);
24                 }
25             }
26             int ans = 0;
27             for(int i = 0; i <= v; i++){    //找到最大值
28                 ans = max(ans, dp[i]);
29             }
30             printf("%d\n", ans);
31         }
32     }
33     return 0;
34 }