动态规划解背包问题.docx
- 文档编号:24005975
- 上传时间:2023-05-23
- 格式:DOCX
- 页数:6
- 大小:16.69KB
动态规划解背包问题.docx
《动态规划解背包问题.docx》由会员分享,可在线阅读,更多相关《动态规划解背包问题.docx(6页珍藏版)》请在冰豆网上搜索。
动态规划解背包问题
利用动态规划算法解0-1背包问题
一、动态规划算法介绍
动态规划算法(DynamicProgrammingAlgorithm,DPA)与分治法类似,其基本思想是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
与分治法不同的是,适合于用动态规划法求解的问题,经分解得到的子问题往往不是互相独立的,若用分治法解这类问题,则分解得到的子问题数目太多,以至于最后解决原问题需要耗费过多的时间。
在用分治法求解时,有些子问题被重复计算了许多次。
如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算。
为了达到此目的,可以用一个表来记录所有已解决的子问题的答案。
这就是动态规划法的基本思想。
动态规划算法使用于解最优化问题。
通常可按以下4个步骤设计:
1、找出最优解的性质,并刻画其结构特征;
2、递归地定义最优值;
3、以自底向上的方式计算出最优值;
4、根据计算最优值时得到的信息,构造最优解。
步骤1~3是动态规划算法的基本步骤。
在只需要求出最优值的情形,步骤4可以省去。
若需要求出问题的最优解,则必须执行步骤4。
此时,在步骤3中计算最优值时,通常需记录更多的信息,以便在步骤4中,根据所记录的信息,快速构造出一个最优解。
二、0-1背包问题
【问题描述】:
给定n种物品和一背包。
物品i的重量是wi,其价值为vi,背包容量为c。
问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大。
在选择装入背包的物品时,对每种物品i只有两种选择,即装入背包或不装入背包。
不能将物品i装入背包多次,也不能只装入部分的物品i。
因此,该问题称为0-1背包问题。
【算法分析】:
0-1背包问题的最优子结构,设(y1,y2,...,yn)是所给0-1背包问题的一个最优解,则(y2,y3,...,yn)是经过一次选择后的0-1背包问题的最优解。
0-1背包问题的递归关系,设当前子问题的最优值为m(i,j),即m(i,j)使背包容量为j,可选择物品为i,i+1,...,n时0-1背包问题的最优值。
由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式:
当i=n时,若j>=wn,则m(i,j)=vn;若0<=j 当i 【算法实现】Knapsack算法的C++实现如下: (其中背包信息从文件中读取,点击进入该文件下载界面) viewsourceprint? 001#include"iostream" 002usingnamespacestd; 003 004#definen50 //物品的数量 005 006//物体重量、收益、背包容量 007intweight[n],profit[n],contain,x[n],**m; 008 009//从文件中读取背包信息 010intread_infor() 011{ 012 FILE*fp; 013 inti; 014 if((fp=fopen("knapsack.txt","r"))==NULL) 015 { 016 printf("Thefileisnotfound! "); 017 return0; 018 } 019 //读取物体收益信息 020 for(i=0;i 021 { 022 fscanf(fp,"%d",&profit[i]); 023 } 024 //读取物体重量信息 025 for(i=0;i 026 { 027 fscanf(fp,"%d",&weight[i]); 028 } 029 //读取背包容量 030 fscanf(fp,"%d",&contain); 031 fclose(fp); 032 return1; 033} 034 035voidKnapsack() 036{ 037 intjMax=min(weight[n-1]-1,contain); 038 inti,j; 039 for(j=0;j<=jMax;j++) 040 { 041 m[n-1][j]=0; 042 } 043 for(j=weight[n-1];j<=contain;j++) 044 { 045 m[n-1][j]=profit[n-1]; 046 } 047 for(i=n-2;i>0;i--) 048 { 049 jMax=min(weight[i]-1,contain); 050 for(j=0;j<=jMax;j++) 051 { 052 m[i][j]=m[i+1][j]; 053 } 054 for(j=weight[i];j<=contain;j++) 055 { 056 m[i][j]=max(m[i+1][j],m[i+1][j-weight[i]]+profit[i]); 057 } 058 } 059 m[0][contain]=m[1][contain]; 060 if(contain>=weight[0]) 061 { 062 m[0][contain]=max(m[0][contain],m[1][contain-weight[0]]+profit[0]); 063 } 064} 065 066voidTraceback() 067{ 068 intc=contain; 069 for(inti=0;i 070 { 071 if(m[i][c]==m[i+1][c]) 072 { 073 x[i]=0; 074 } 075 else 076 { 077 x[i]=1; 078 c-=weight[i]; 079 } 080 } 081 x[n-1]=(m[n-1][c])? 1: 0; 082} 083 084voidmain() 085{ 086 inti,sumWeight=0; 087 if(read_infor()) 088 { 089 m=(int**)malloc(n*sizeof(int*)); 090 for(i=0;i 091 { 092 m[i]=(int*)malloc(contain*sizeof(int)); 093 } 094 Knapsack(); 095 Traceback(); 096 } 097 printf("Thechoiceis: \n"); 098 for(i=0;i 099 { 100 sumWeight+=weight[i]*x[i]; 101 if(i! =0&&i%5==0) 102 { 103 printf(""); 104 } 105 printf("%1d",x[i]); 106 } 107 printf("\nThemaximumprofitis: %d.",m[1][contain]); 108 printf("\nTheknapsackweightis%d.\n",sumWeight); 109 scanf("%d",&i); 110 for(i=0;i 111 { 112 free(m[i]); 113 } 114 free(m); 115} 【算法复杂度分析】: 从计算m(i,j)的递归式容易看出,上述算法Knapsack需要O(nc)计算时间,而Traceback需要O(n)计算时间。 其中,算法Knapsack还存在可以改进的地方,改进算法将在后续的文章中给出。 Resources&Reference: 1、王晓东.计算机算法设计与分析(第3版)[M].北京: 电子工业出版社,2009,77-78.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 动态 规划 背包 问题