动态规划之0-1背包问题
2013-08-28 10:52
316 查看
本博客已迁往http://coredumper.cn
0-1背包问题的解决思路如下:假设可选物品的个数为SIZE,用0~SIZE-1分别表示每个物品的索引号,数组w[SIZE]表示每个物品的重量,数组v[SIZE]表示每个物品的价值,f(i, aw)表示当可选取的物品索引号在0~i之间,并且背包还可以容纳的重量为aw时的最大价值。
则有如下4中情况:
当i=0且w[i]>aw时,f(i, aw)=0
当i=0且w[i]<=aw时,f(i, aw)=v[i]
当i>0且w[i]>aw时,f(i, aw)=f(i-1, aw)
当i>0且w[i]<=aw时,f(i, aw)=max( f(i-1, aw), v[i]+f(i-1, aw-w[i]) )
下面分别给出原始递归算法和动态规划的备忘录方法的源码。
原始递归算法,该算法需要大量重复计算相同子问题:
#include <stdio.h> #define SIZE 10 //可选的物品数量 #define AW 20 //背包可以装下的最大重量 /* 参数w代表每种物品的重量,参数v代表每种物品的价值, 参数index代表物品的索引号,参数aw代表背包还可以容纳的重量*/ int knapSack(int w[], int v[], int index, int aw) { if(index == 0){ if(w[index] <= aw){ return v[index]; } return 0; } int withoutIndex, withIndex; withoutIndex = knapSack(w, v, index - 1, aw); if(w[index] > aw){ return withoutIndex; } withIndex = v[index] + knapSack(w, v, index - 1, aw - w[index]); if(withoutIndex > withIndex){ return withoutIndex; } return withIndex; } int main() { int w[SIZE] = {5, 3, 2, 7, 8, 9, 10, 5, 3, 2}; int v[SIZE] = {9, 7, 8, 10, 11, 15, 20, 8, 6, 7}; printf("%d\n", knapSack(w, v, SIZE - 1, AW)); return 0; }
动态规划的备忘录方法:
/* 用二维数组m[i][j]存放当可选取的物品索引号在0~i之间, 并且背包还可以容纳的重量为j时的最大价值,可避免重复解决相同子问题。 */ #include <stdio.h> #define SIZE 10 #define AW 20 int knapSack(int w[], int v[], int index, int aw, int m[][AW+1]) { if(m[index][aw] != -1){ return m[index][aw]; } if(index == 0){ if(w[index] <= aw){ m[index][aw] = v[index]; return v[index]; } m[index][aw] = 0; return 0; } int withoutIndex, withIndex; withoutIndex = knapSack(w, v, index - 1, aw, m); if(w[index] > aw){ m[index][aw] = withoutIndex; return withoutIndex; } withIndex = v[index] + knapSack(w, v, index - 1, aw - w[index], m); if(withoutIndex > withIndex){ m[index][aw] = withoutIndex; return withoutIndex; } m[index][aw] = withIndex; return withIndex; } int memKS(int w[], int v[], int index, int aw) { int m[SIZE][AW+1]; int i, j; for(i = 0; i < SIZE; ++i){ for(j = 0; j <= AW; ++j){ m[i][j] = -1; } } return knapSack(w, v, index, aw, m); } int main() { int w[SIZE] = {5, 3, 2, 7, 8, 9, 10, 5, 3, 2}; int v[SIZE] = {9, 7, 8, 10, 11, 15, 20, 8, 6, 7}; printf("%d\n", memKS(w, v, SIZE - 1, AW)); return 0; }
备忘:以上给出的两种解法均只能计算出最大价值,但是没有给出应该取出物品的索引号;另外还缺少动态规划的迭代方法。
相关文章推荐
- 动态规划——背包问题
- 动态规划解决背包问题
- 动态规划之背包问题
- 动态规划-背包问题九讲及其代码实现
- 动态规划的经典问题————背包问题(一)
- 算法导论16.2-2--动态规划(0-1背包问题)
- 0/1背包问题-----动态规划求解
- 动态规划---0-1背包问题
- 动态规划之0-1背包问题
- 九度OJ 1532 棋盘寻宝扩展 -- 动态规划【背包问题】
- POJ 3132 Sum of Different Primes 动态规划 DP 0-1背包问题
- java--0-1背包问题--动态规划解法
- 集合问题 动态规划 01背包
- 动态规划解0-1背包问题(C语言版)
- 动态规划解决0-1背包问题
- Python动态规划计算0-1背包问题的最优值
- 0/1背包问题(二)---动态规划
- 动态规划求解0-1背包问题
- 动态规划 (Dynamic Programming) 之 背包问题合辑 (Knapsack, Subset Sum, Partition and change making problem )
- 动态规划-3.9 0-1背包问题