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)

posted @ 2017-09-02 11:30  hedgehog小子  阅读(1914)  评论(0编辑  收藏  举报