DP:0-1背包問題


【問題描述】

0-1背包問題:有 N 個物品,物品 i 的重量為整數 wi >=0,價值為整數 vi >=0,背包所能承受的最大重量為整數 C。如果限定每種物品只能選擇0個或1個,求可裝的最大價值。
可以用公式表示為:
 【算法思路】

動態規划法。我們可以想到這個問題具有最優子結構性質,假設(x1,x2,...,xn)是最優解,那么在去除x1之后,剩下(x2,...,xn)肯定是以下問題的最優解:

根據這個特征可以設計DP函數並推出遞歸關系。具體地,m(i,j)是背包容量為j,可選擇物品為i,i+1,…,n時0-1背包問題的最優值。由0-1背包問題的最優子結構性質,則:

按着DP[N][C]的矩陣一個一個從 下 往 上 填就可以了,最后的結果是 DP(1,C)。要輸出選取的樣本編號的時候可以從前往后, DP(1,C)== DP(2,C),則x1=0,否則1,依次類推即可。

【代碼】

 1 #include<iostream>
 2 #include<algorithm>
 3 #include <stdio.h>
 4 #define MAXN 10000
 5 using namespace std;
 6 
 7 int W[MAXN];
 8 int V[MAXN];
 9 int DP[MAXN][MAXN]= {0};
10 
11 int knapsack(int C, int N, int W[], int V[], int DP[][MAXN])
12 {
13     int lackL = min(C, W[N]-1);
14     for(int j = 0; j <=lackL; j++) DP[N][j] = 0;
15     for(int j = W[N]; j <=C; j++) DP[N][j] = V[N];
16     for(int i = N - 1; i>=1; i--){
17         lackL = min(C, W[i]-1);
18         for(int j = 0; j <=lackL; j++) DP[i][j] = DP[i+1][j];
19         for(int j = W[i]; j <=C; j++){
20             DP[i][j] = max( DP[i+1][j], DP[i+1][j-W[i]] + V[i] );
21         }
22     }
23     return DP[1][C];
24 }
25 
26 int main()
27 {
28     int C, N;
29     cin >> C >> N;
30     for(int i = 1; i <=N; i++) {
31         cin >> W[i] >> V[i];
32     }
33     cout<<knapsack(C, N, W, V, DP)<<endl;
34 
35     return 0;
36 }

 

 【拓展】

如果現在的物品重量weight和背包容量C都是正整數,那么當他們是實數時,如何改進算法滿足問題呢?

待完善(算法設計與分析P73)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM