2022年0-1背包问题四种不同算法的实现. .pdf
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_05.gif)
《2022年0-1背包问题四种不同算法的实现. .pdf》由会员分享,可在线阅读,更多相关《2022年0-1背包问题四种不同算法的实现. .pdf(25页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、兰州交通大学数理与软件工程学院题目 0-1 背包问题算法实现院系数理院专业班级信计 09 学生姓名雷雪艳学号200905130 指导教师李秦二一二年六 月 五 日名师归纳总结 精品学习资料 - - - - - - - - - - - - - - -精心整理归纳 精选学习资料 - - - - - - - - - - - - - - - 第 1 页,共 25 页 - - - - - - - - - 一、问题描述:1、01 背包问题:给定n 种物品和一个背包,背包最大容量为M,物品 i 的重量是 wi,其价值是平 Pi,问应当如何选择装入背包的物品,似的装入背包的物品的总价值最大?背包问题的数学描述
2、如下:2、要求找到一个 n 元向量 (x1,x2xn),在满足约束条件:10iiixMwx情况下,使得目标函数pxiimax,其中,1in;M0;wi0;pi0。满足约束条件的任何向量都是一个可行解,而使得目标函数达到最大的那个可行解则为最优解1。给定 n 种物品和 1 个背包。物品 i 的重量是 wi,其价值为 pi,背包的容量为 M。问应如何装入背包中的物品,使得装人背包中物品的总价值最大?在选择装人背包的物品时,对每种物品i 只有两种选择,即装入背包、不装入背包。不能将物品i 装人背包多次,也不能只装入部分的物品i。该问题称为 0-1 背包问题。0-1 背包问题的符号化表示是,给定M0,
3、 w i 0, pi 0,1in ,要求找到一个 n 元 0-1 向量向量 (x1,x2xn), X i =0 或 1 , 1in, 使得Mwxii,而且pxii达到最大2。二、解决方案:方案一:贪心算法1、贪心算法的基本原理与分析贪心算法总是作出在当前看来是最好的选择,即贪心算法并不从整体最优解上加以考虑, 它所作出的选择只是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广的许多问题它能产生整体最优解。 在一些情况下, 即使贪心算法不能得到整体最优解,但其最终结果却是最优解的很好近似解。贪心算法求解的问题一般具有两个重要性质:贪心选择性质和最优子结构性质。所
4、谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优解的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。当一个问题的最优解包含其子问题的最优解时, 称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。2、0-1 背包问题的实现对于 0-1 背包问题,设 A 是能装入容量为c 的背包的具有最大价值的物品集合,则 Aj=A-j 是 n-1 个物品 1,2,.,j-1,j+1,.,n 可装入容量为 c-wj 的背包的具有最大价值的物品集合。用贪心算法求解0-1 背包问题的步骤是,首先计算每种物品单位
5、重量的价值 vi/wi ;然后,将物品进行排序,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。 若将这种物品全部装入背包后,背包内的物名师归纳总结 精品学习资料 - - - - - - - - - - - - - - -精心整理归纳 精选学习资料 - - - - - - - - - - - - - - - 第 2 页,共 25 页 - - - - - - - - - 品总量未超过 c,则选择单位重量价值次高的物品并尽可能多地装入背包。依此策略一直进行下去,直到背包装满为止。3、算法设计如下:#include #define max 100 /最多物品数void sort (int
6、 n,float amax,float bmax) /按价值密度排序 int j,h,k; float t1,t2,t3,cmax; for(k=0;kn;k+) ck=ak/bk; for(j=0;jn;j+) if(cjcj+1) t1=aj;aj=aj+1;aj+1=t1; t2=bj;bj=bj+1;bj+1=t2; t3=cj;cj=cj+1;cj+1=t3; void knapsack(int n,float limitw,float vmax,float wmax,int xmax) float c1; /c1 为背包剩余可装载重量int i; sort(n,v,w); /物品按
7、价值密度排序c1=limitw; for(i=0;ic1)break; xi=1; /xi 为 1 时,物品 i 在解中c1=c1-wi; void main() int n,i,xmax; float vmax,wmax,totalv=0,totalw=0,limitw; coutn limitw; for(i=1;i=n;i+) xi=0; /物品选择情况表初始化为0 cout请依次输入物品的价值:endl; for(i=1;ivi; coutendl; cout请依次输入物品的重量:endl; for(i=1;iwi; coutendl; knapsack (n,limitw,v,w,x
8、); coutthe selection is:; for(i=1;i=n;i+) coutxi; if(xi=1) totalw=totalw+wi; totalv=totalv+vi; coutendl; cout 背 包 的 总 重 量 为 :totalwendl; /背包所装载总重量cout 背 包 的 总 价 值 为 :totalvendl; / 背包的总价值4、贪心算法运行结果如下图所示:名师归纳总结 精品学习资料 - - - - - - - - - - - - - - -精心整理归纳 精选学习资料 - - - - - - - - - - - - - - - 第 3 页,共 25
9、页 - - - - - - - - - 方案二:动态规划算法1、动态规划的基本原理与分析动态规划算法的基本思想是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。但是经分解得到的子问题往往不是互相独立的。不同子问题的数目常常只有多项式量级。如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法。它把已知问题分为很多子问题,按顺序求解子问题,在每一种情况下,列出各种情况的局部解,按条件从中选取那些最有可能产生最佳的结果舍弃其余。前一子问题为后面子问题提供信息,而减少计算量,最后一个子问题的解即为问题解。采用此
10、方法求解0-1 背包问题的主要步骤如下:分析最优解的结构:最有子结构性质;建立递归方程;计算最优值;构造最优解4。2、 0-1 背包问题的实现 最优子结构性质0-1 背包问题具有最优子结构性质。设(y1,y2yn)是所给 0-1 背包问题的一个最优解,则 (y2,y3yn)是下面相应子问题的一个最优解:nikkkxvmaxnkixjxwknikkk,1 , 0因若不然,设 (z2,z3zn)是上述问题的一个最优解,而(y2,y3yn)不是它的最优解,由此可见ni 2niiiyv2,且niiizw2w1y1c。因此niiizv2v1y1niiiyv1名师归纳总结 精品学习资料 - - - - -
11、 - - - - - - - - - -精心整理归纳 精选学习资料 - - - - - - - - - - - - - - - 第 4 页,共 25 页 - - - - - - - - - niiizw2w1y1c 这说明 (y1,z2zn)是所给 0-1 背包问题的一个更优解,从而(y1,y2yn)不是所给 0-1 背包问题的最优解。此为矛盾1。 递归关系设所给 0-1 背包问题的子问题nikkkxvmaxnkixjxwknikkk,1 ,0的最优值为 m(i,j),即 m(i,j) 是背包容量为 j,可选择物品为i,i+1,n 时 0-1 背包问题的最优值。由0-1 背包问题的最优子结构性
12、质,可以建立计算 m(i,j)的递归式如下:wjjjimwijviwijimjim0), 1(,), 1(),),1(maxj)m(i,wnjwnvnj0j)m(n,3、算法设计如下:#include #include using namespace std; const int MAX=1000; int wMAX,vMAX,bestMAX; int VMAXMAX; /最大价值矩阵int W,n; /W为背包的最大载重量, n 为物品的数量/求最大值函数int max(int x,int y) return x = y?x:y; /求最小值函数int min(int x,int y) re
13、turn x= y ? y:x; void Knaspack() int Max=min(wn-1,W); for(int j=1; j = Max ; j+) Vnj=0; for( j=wn; j 1 ; i-) Max=min(wi-1,W); for( j=1; j = Max ; j+) Vij=Vi+1j; for( j=wi; j w1) V1W=max(V1W,V2W-w1+v1); /生成向量数组,决定某一个物品是否应该放入背包void Traceback() for(int i=1; i n ; i+) /比较矩阵两邻两行 (除最后一行 ),背包容量为 W 的最优值 . i
14、f(ViW = Vi+1W) /如果当前行的最优值与下一行的最优值相等, 则表明该物品不能放入。besti=0; else /否则可以放入 besti=1; W-=wi; bestn=(VnW )?1:0; void main() coutnW; cout输入每件商品的重量w:endl; for(int i=1;iwi; memset(V ,0,sizeof(V); cout输入每件商品的价值v:endl; for( i=1;ivi; Knaspack();/构造矩阵Traceback(); /求出解的向量数组int totalW=0; int totalV=0; /显示可以放入的物品cout
15、 所 选 择 的 商 品 如下:endl; cout序 号 i: 重量 w: 价 格v:endl; for(i=1; i = n ; i+) if(besti = 1) totalW+=wi; totalV+=vi; coutsetiosflags(ios:left)setw(5)i wi viendl; cout放入的物品重量总和是:totalW 价值最优解是:V1W totalVendl; 4、计算复杂性分析利用动态规划求解0-1 背包问题的复杂度为0(minnc,2n 。动态规划主要是求解最优决策序列,当最优决策序列中包含最优决策子序列时,可建立动态规划递归方程,它可以帮助高效地解决问题
16、8。5、动态规划运行结果如下图所示:名师归纳总结 精品学习资料 - - - - - - - - - - - - - - -精心整理归纳 精选学习资料 - - - - - - - - - - - - - - - 第 6 页,共 25 页 - - - - - - - - - 方案三:回溯法1、回溯法的基本原理与分析回溯是一种系统地搜索问题解答的方法。为了实现回溯, 首先需要为问题定义一个解空间,这个解空间必须至少包含问题的一个解(可能是最优的 )。回溯法需要为问题定义一个解空间,这个解空间必须至少包含问题的一个解(可能是最优的 )。使用递归回溯法解决背包问题的优点在于它算法思想简单,而且它能完全遍
17、历搜索空间,肯定能找到问题的最优解奉但是由于此问题解的总组合数有n2个,因此随着物件数 n 的增大,其解的空间将以nn2级增长,当 n 大到一定程度上,用此算法解决背包问题将是不现实的。下一步是组织解空间以便它能被容易地搜索。典型的组织方法是图或树。一旦定义了解空间的组织方法,这个空间即可按照深度优先的方法从开始结点进行搜索,利用限界函数避免移动到不可能产生解的子空间。2、 0-1 背包问题的实现回溯法是一种系统地搜索问题解答的方法。为了实现回溯,首先需要为问题定义一个解空间,这个解空间必须至少包含问题的一个解(可能是最优的)。一旦定义了解空间的组织方要选择一个对象的子集,将它们装人背包,以便
18、获得的收益最大,则解空间应组织成子集树的形状。首先形成一个递归算法,去找到可获得的最大收益。然后,对该算法加以改进,形成代码。改进后的代码可找到获得最大收益时包含在背包中的对象的集合。左子树表示一个可行的结点,无论何时都要移动到它,当右子树可能含有比当前最优解还优的解时,移动到它。一种决定是否要移动到右子树的简单方法是 r 为还未遍历的对象的收益之和,将r 加到 cp (当前节点所获收益 )之上,若 ( r+cp) bestp(目前最优解的收益 ),则不需搜索右子树。一种更有效的方法是按收益密度vi/wi 对剩余对象排序,将对象按密度递减的顺序去填充背包的剩余容量,当遇到第一个不能全部放人背包
19、的对象时,就使用它的一部分。3、算法设计如下:#include using namespace std; class Knap friend int Knapsack(int p,int w,int c,int n ); public: void print() for(int m=1;m=n;m+) 名师归纳总结 精品学习资料 - - - - - - - - - - - - - - -精心整理归纳 精选学习资料 - - - - - - - - - - - - - - - 第 7 页,共 25 页 - - - - - - - - - coutbestxm ; coutendl; ; priva
20、te: int Bound(int i); void Backtrack(int i); int c;/背包容量int n; /物品数int *w;/ 物品重量数组int *p;/ 物品价值数组int cw;/当前重量int cp;/当前价值int bestp;/当前最优值int *bestx;/当前最优解int *x;/ 当前解; int Knap:Bound(int i) /计算上界int cleft=c-cw;/剩余容量int b=cp; /以物品单位重量价值递减序装入物品while(i=n&wi=cleft) cleft-=wi; b+=pi; i+; /装满背包if(in) if(b
21、estpcp) for(int j=1;j=n;j+) bestxj=xj; bestp=cp; return; if(cw+wibestp)/ 搜索右子树 xi=0; Backtrack(i+1); class Object friend int Knapsack(int p,int w,int c,int n); public: int operator=a.d); private: int ID; float d; ; int Knapsack(int p,int w,int c,int n) /为 Knap:Backtrack 初始化int W=0; int P=0; int i=1;
22、 Object *Q=new Objectn; for(i=1;i=n;i+) Qi-1.ID=i; 名师归纳总结 精品学习资料 - - - - - - - - - - - - - - -精心整理归纳 精选学习资料 - - - - - - - - - - - - - - - 第 8 页,共 25 页 - - - - - - - - - Qi-1.d=1.0*pi/wi; P+=pi; W+=wi; if(W=c) return P;/装入所有物品/依物品单位重量排序float f; for( i=0;in;i+) for(int j=i;jn;j+) if(Qi.dQj.d) f=Qi.d;
23、Qi.d=Qj.d; Qj.d=f; Knap K; K.p = new intn+1; K.w = new intn+1; K.x = new intn+1; K.bestx = new intn+1; K.x0=0; K.bestx0=0; for( i=1;i=n;i+) K.pi=pQi-1.ID; K.wi=wQi-1.ID; K.cp=0; K.cw=0; K.c=c; K.n=n; K.bestp=0; /回溯搜索K.Backtrack(1); K.print(); delete Q; delete K.w; delete K.p; return K.bestp; void ma
24、in() int *p; int *w; int c=0; int n=0; int i=0; char k; while(k) cout 请 输 入 背 包 容 量 (c):c; cout请输入物品的个数(n):n; p=new intn+1; w=new intn+1; p0=0; w0=0; cout请输入物品的价值(p):endl; for(i=1;ipi; cout请输入物品的重量 (w):endl; for(i=1;iwi; cout 最 优 解 为 (bestx) :endl; cout 最 优 值 为 (bestp) :endl; coutKnapsack(p,w,c,n)en
25、dl; couts 重新开始endl; coutq 退出k; 4、运行结果如下图所示:名师归纳总结 精品学习资料 - - - - - - - - - - - - - - -精心整理归纳 精选学习资料 - - - - - - - - - - - - - - - 第 9 页,共 25 页 - - - - - - - - - 方案四:分枝 -限界法1、分枝 -限界法的基本原理与分析分枝限界发是另一种系统地搜索解空间的方法,它与回溯法的主要区别在于对 E-结点(expansion node) 的扩充方式。 每个活结点有且仅有一次会变成E-结点。当一个结点变为E-结点时,则生成从该结点移动一步即可到达的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年0-1背包问题四种不同算法的实现. 2022 背包 问题 不同 算法 实现
![提示](https://www.taowenge.com/images/bang_tan.gif)
限制150内