动态规划算法01背包问题PPT

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

//输出Fibonacii数列的第n项的动态规划算法 #include <stdio.h> #define MAX 50 int fib(int n) { int i,a[MAX]; a[1]=a[2]=1; for (i=3; i<=n; i++) a[i]=a[i-1]+a[i-2]; return a[n]; } void main( ) { int n; scanf("%d",&n); printf("%d\n" ,fib( n ) ); }
void knapsack() { int i,j; for (j=w[n]; j<=c; j++) m[n][j]=v[n]; for (i=n-1; i>=1;i--) for (j=w[i]; j<=c; j++) if ( m[i+1][j]>m[i+1][j-w[i]]+v[i] ) m[i][j]=m[i+1][j]; else m[i][j]=m[i+1][j-w[i]]+v[i]; }
//显示所取的物品及其重量(其中一个解) //对数组m的最后一列检查来求解 void disp( ) { int i来自百度文库j; i=n; while ( m[i][c]==m[i-1][c] ) i--; while (i>0) { j=i-1; while (m[i][c]-m[j][c]!=v[i-1] && j>0) j--; printf("%5d%5d\n",w[i-1],v[i-1]); i=j; } }
void main( ) { int i,j; printf("输入物品种数:"); scanf("%d",&n); printf("输入每种物品的重量与价值:\n"); for (i=1; i<=n; i++) scanf("%d%d",&w[i],&v[i]); printf("输入背包的总重量:\n"); scanf("%d",&c); knapsack(); disp(); printf("最大价值=%d\n",m[0][c]); for (i=1; i<=n; i++) { for (j=0; j<=c; j++) printf("%3d",m[i][j]); printf("\n"); } }
void main( ) { int i,j; printf("输入物品种数:"); scanf("%d",&n); printf("输入每种物品的重量与价值:\n"); for (i=0; i<n; i++) scanf("%d%d",&w[i],&v[i]); printf("输入背包的总重量:\n"); scanf("%d",&c); knapsack(); disp(); printf("最大价值=%d\n",m[n][c]); for (i=0; i<=n; i++) { for (j=0; j<=c; j++) printf("%3d",m[i][j]); printf("\n"); } }
例1:0-1背包问题
有一个负重能力为m的背包和不同价值v[i]、不同 重量w[i] 的物品n 件。在不超过负重能力的前提下, 从这n件物品中任意选择物品,使这些物品的价值之 和最大。
物品 重量 价值 1 5 4 2 3 4 3 2 3 4 1 1
算法思想1:设m[i][j]用来表示从第i项物品开始 到第n项物品中区取出装入体积为j的背包的物品的最 大价值。其中i的范围为1到n,其中j的范围为0到c, 程序要寻求的解为m[1][c]。可以发现: ①m[n][j] 在当j>=0并且j< w[n] 时等于0,否则等 于v[n] ②当前的背包容量j大于等于物品重量w[i]时, m[i][j]是下面两个量的最大值:m[i+1][j] 和 m[i+1][ jw[i] ]+v[i] ③当前的背包容量j小于物品重量w[i]时, m[i][j]等于m[i+1][j]。 当j<w[i] m[i][j]= m[i+1][j] Max(m[i+1][j], m[i+1][j-w[i] ]+v[i] ) 当j>=w[i] m[n][j]= v[n] 0 当j>=w[n] 当j>=0 并且 j< w[n]
算法思想2:设m[i][j]用来表示从前i项物品中区 取出装入体积为j的背包的物品的最大价值。其中i的范 围为1到n,其中j的范围为0到c,程序要寻求的解为 m[n][c]。可以清楚地发现: ①m[0][j]对所有的j的值为0, m[i][0]对所有的i的 值为0。 ②当前的体积j大于等于w[i]时, m[i][j]是 下面两个量的最大值:m[i-1][j] 和 m[i-1][j-w[i]]+v[i] ③当前的体积j小于w[i]时,m[i][j]等于m[i-1][j] 0 i=0 或者 j=0 m[i][j]= m[i-1][j] j>0且j<w[i] Max(m[i-1][j], m[i-1][j-w[i] ]+v[i] ) i>0且j>=w[i]
//程序2:动态规划法 #include <stdio.h> #define MAX 20 int n,c,w[MAX],v[MAX],m[MAX][MAX]={0}; void knapsack() { int i,j; for (i=1; i<=n; i++) for (j=1; j<=c; j++) { m[i][j]=m[i-1][j]; if ( j>=w[i-1] && m[i-1][j-w[i-1]]+v[i-1]> m[i][j] ) m[i][j]=m[i-1][j-w[i-1]]+v[i-1]; } }
例:输出Fibonacii数列的第n项的递归算法
#include <stdio.h> int fib(int n) { if (n<=1) return 1; else return fib(n-1)+fib(n-2); } void main( ) { int n; scanf("%d",&n); printf("%d\n" ,fib( n ) ); } 在上面的递归算法中存在多次计算同一个子问 题,如:fib(2)。如果能将这样的子问题的解用数组 保存起来,即可以加快求解的过程,即采用动态规 划方法。
//程序1:动态规划法 #include <stdio.h> #define MAX 20 int n,c,w[MAX],v[MAX],m[MAX][MAX]={0}; void disp( ) { int i; for (i=1; i<=n; i++) if ( m[i][c]!=m[i+1][c] ) printf("%5d%5d\n",w[i],v[i]); }
相关文档
最新文档