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 }