ImageVerifierCode 换一换
格式:DOCX , 页数:25 ,大小:252.73KB ,
资源ID:12453131      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/12453131.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(用蛮力法动态规划法和贪心法求解01背包问题讲解.docx)为本站会员(b****0)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

用蛮力法动态规划法和贪心法求解01背包问题讲解.docx

1、用蛮力法动态规划法和贪心法求解01背包问题讲解算法设计与分析项 目 名 称:用蛮力法、动态规划法和贪心法求解0/1背包问题作者姓名:余武丹李红波刘红梅完成日期:2013年9月20日第一章:简介(Introduction)第二章:算法定义(Algorithm Specification)第三章:测试结果(Testing Results)第四章:分析和讨论第一章:简介(Introduction) 0/1背包问题是给定n个重量为w1, w2, ,wn、价值为v1, v2, ,vn的物品和一个容量为C的背包,求这些物品中的一个最有价值的子集,并且要能够装到背包中。在0/1背包问题中,物品i或者被装入背

2、包,或者不被装入背包,设xi表示物品i装入背包的情况,则当xi=0时,表示物品i没有被装入背包,xi=1时,表示物品i被装入背包。根据问题的要求,有如下约束条件和目标函数: 于是,问题归结为寻找一个满足约束条件式1,并使目标函数式2达到最大的解向量X=(x1, x2, , xn)。背包的数据结构的设计:typedef struct object int n;/物品的编号 int w;/物品的重量 int v;/物品的价值wup;wup wpN;/物品的数组,N为物品的个数int c;/背包的总重量第二章:算法定义(Algorithm Specification)1、蛮力法蛮力法是一种简单直接的

3、解决问题的方法,常常直接基于问题的描述和所涉及的概念定义。蛮力法的关键是依次处理所有的元素。用蛮力法解决0/1背包问题,需要考虑给定n个物品集合的所有子集,找出所有可能的子集(总重量不超过背包容量的子集),计算每个子集的总价值,然后在他们中找到价值最大的子集。所以蛮力法解0/1背包问题的关键是如何求n个物品集合的所有子集,n个物品的子集有2的n次方个,用一个2的n次方行n列的数组保存生成的子集,以下是生成子集的算法:void force(int a4)/蛮力法产生4个物品的子集 int i,j; int n=16; int m,t; for(i=0;i=0;j-) m=t%2; aij=m;

4、t=t/2; for(i=0;i16;i+)/输出保存子集的二维数组 for(j=0;j4;j+) printf(%d ,aij); printf(n); 以下要依次判断每个子集的可行性,找出可行解:void panduan(int a4,int cw)/判断每个子集的可行性,如果可行则计算其价值存入数组cw,不可行则存入0 int i,j; int n=16; int sw,sv; for(i=0;i16;i+) sw=0; sv=0; for(j=0;j4;j+) sw=sw+wpj.w*aij; sv=sv+wpj.v*aij; if(sw=c) cwi=sv; else cwi=0;

5、在可行解中找出最优解,即找出可行解中满足目标函数的最优解。以下是找出最优解的算法:int findmax(int x164,int cv)/可行解保存在数组cv中,最优解就是x数组中某行的元素值相加得到的最大值 int max; int i,j; max=0; for(i=0;imax) max=cvi; j=i; printf(n最好的组合方案是:); for(i=0;i4;i+) printf(%d ,xji); return max;。2、动态规划法动态规划法将待求解问题分解成若干个相互重叠的子问题,每个子问题对应决策过程的一个阶段,一般来说,子问题的重叠关系表现在对给定问题求解的递推关

6、系(也就是动态规划函数)中,将子问题的解求解一次并填入表中,当需要再次求解此子问题时,可以通过查表获得该子问题的解而不用再次求解,从而避免了大量重复计算。动态规划法设计算法一般分成三个阶段:(1)分段:将原问题分解为若干个相互重叠的子问题;(2)分析:分析问题是否满足最优性原理,找出动态规划函数的递推式;(3)求解:利用递推式自底向上计算,实现动态规划过程。 0/1背包问题可以看作是决策一个序列(x1, x2, , xn),对任一变量xi的决策是决定xi=1还是xi=0。在对xi-1决策后,已确定了(x1, , xi-1),在决策xi时,问题处于下列两种状态之一:(1)背包容量不足以装入物品i

7、,则xi=0,背包不增加价值;(2)背包容量可以装入物品i,则xi=1,背包的价值增加了vi。 这两种情况下背包价值的最大者应该是对xi决策后的背包价值。令V(i, j)表示在前i(1in)个物品中能够装入容量为j(1jC)的背包中的物品的最大值,则可以得到如下动态规划函数: V(i, 0)= V(0, j)=0 (式3) (式4)式3表明:把前面i个物品装入容量为0的背包和把0个物品装入容量为j的背包,得到的价值均为0。式4的第一个式子表明:如果第i个物品的重量大于背包的容量,则装入前i个物品得到的最大价值和装入前i-1个物品得到的最大价值是相同的,即物品i不能装入背包;第二个式子表明:如果

8、第i个物品的重量小于背包的容量,则会有以下两种情况:(1)如果把第i个物品装入背包,则背包中物品的价值等于把前i-1个物品装入容量为j-wi的背包中的价值加上第i个物品的价值vi;(2)如果第i个物品没有装入背包,则背包中物品的价值就等于把前i-1个物品装入容量为j的背包中所取得的价值。显然,取二者中价值较大者作为把前i个物品装入容量为j的背包中的最优解。 以下是动态规划法求解背包问题的算法:int findmaxvalue(wup *p,int x)/x数组用来存放可行解,p是指向存放物品数组的指针 int i,j; int maxvalue; int valueN+1C+1; for(j=

9、0;j=C;j+) value0j=0; /初始化第0行 for(i=0;i=N;i+) valuei0=0;/初始化第0列 /计算数组value中各元素的值 for(i=1;i=N;i+,p+) for(j=1;jw j) valueij=valuei-1j; else valueij=max(valuei-1j,(valuei-1j-p-w+p-v);/max函数求两个数当中的大者 /逆推求解 j=C; for(i=N;i0;i-) if(valueijvaluei-1j) xi-1=1;/是否被选中的向量的下标也是从0开始 j=j-wpi-1.w;/存放物品的下标从0开始 else xi

10、-1=0; maxvalue=valueNC;/最大值 return maxvalue;3、贪心法 贪心法在解决问题的策略上目光短浅,只根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。换言之,贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优。 这种局部最优选择并不总能获得整体最优解(Optimal Solution),但通常能获得近似最优解(Near-Optimal Solution)。贪心法求解的问题的特征:(1)最优子结构性质 当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质,也称此问题满足最优性原理。(2)

11、贪心选择性质 所谓贪心选择性质是指问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来得到。用贪心法求解问题应该考虑如下几个方面:(1)候选集合C:为了构造问题的解决方案,有一个候选集合C作为问题的可能解,即问题的最终解均取自于候选集合C。例如,在付款问题中,各种面值的货币构成候选集合。(2)解集合S:随着贪心选择的进行,解集合S不断扩展,直到构成一个满足问题的完整解。例如,在付款问题中,已付出的货币构成解集合。(3)解决函数solution:检查解集合S是否构成问题的完整解。例如,在付款问题中,解决函数是已付出的货币金额恰好等于应付款。 (4)选择函数select:即贪心策略,这是贪心

12、法的关键,它指出哪个候选对象最有希望构成问题的解,选择函数通常和目标函数有关。例如,在付款问题中,贪心策略就是在候选集合中选择面值最大的货币。(5)可行函数feasible:检查解集合中加入一个候选对象是否可行,即解集合扩展后是否满足约束条件。例如,在付款问题中,可行函数是每一步选择的货币和已付出的货币相加不超过应付款。 背包问题至少有三种看似合理的贪心策略: (1)选择价值最大的物品,因为这可以尽可能快地增加背包的总价值。但是,虽然每一步选择获得了背包价值的极大增长,但背包容量却可能消耗得太快,使得装入背包的物品个数减少,从而不能保证目标函数达到最大。 (2)选择重量最轻的物品,因为这可以装

13、入尽可能多的物品,从而增加背包的总价值。但是,虽然每一步选择使背包的容量消耗得慢了,但背包的价值却没能保证迅速增长,从而不能保证目标函数达到最大。 (3)选择单位重量价值最大的物品,在背包价值增长和背包容量消耗两者之间寻找平衡。应用第三种贪心策略,每次从物品集合中选择单位重量价值最大的物品,如果其重量小于背包容量,就可以把它装入,并将背包容量减去该物品的重量,然后我们就面临了一个最优子问题它同样是背包问题,只不过背包容量减少了,物品集合减少了。因此背包问题具有最优子结构性质。先按单位重量价值最大对物品进行排序,用冒泡排序算法进行排序的算法如下:void bublesort(wup wp) in

14、t i,k; wup p; int flag; for(i=1;i=i; k-) if (wpk-1.v/wpk-1.wwpk.v/wpk.w)/比较物品单位重量的价值,按从大到小排序 p.n =wpk-1.n; p.v=wpk-1.v; p.w=wpk-1.w; wpk-1.n=wpk.n; wpk-1.v=wpk.v; wpk-1.w=wpk.w; wpk.n=p.n; wpk.v=p.v; wpk.w=p.w; flag=1; if(flag=0)break; 然后再用贪心策略选择的算法如下:int tx_findmaxvalue(wup wp,int x)/ 用贪心算法找出放入背包中物

15、品的最佳组合/wp为指向物品数组,x是存放解向量的数组 int i; int cw,maxvalue; cw=C;/cw为中间变量,用来临时存储背包的总重量 bublesort(wp); Outputwp(wp); maxvalue=0; for(i=0;iN;i+)/对已排过序的数组,顺序选择物品是否可以放入背包 if(wpi.wcw) /如果物品的重量小于背包的重量,则放入背包 xwpi.n-1=1; /该物品被选中,对应的向量为1 maxvalue=maxvalue+wpi.v;/累加价值 cw=cw-wpi.w; /每放入一件物品背包的总重量减少 else xwpi.n-1=0; re

16、turn maxvalue;第三章:测试结果(Testing Results)1.蛮力法测试结果:输入完毕后按Enter键有如下结果:2.动态规划法调试结果3.贪心法调试结果:(1).空间最优的贪心策略结果(2).价格最优的贪心策略结果(3).价格空间比最优的贪心策略结果第四章:分析和讨论算法的时间复杂度和空间复杂度的分析,对算法进一步改进的讨论。附录:源代码(基于C语言的)1.蛮力法求解01背包问题源程序:#include stdafx.h#include stdlib.h #include stdio.h#define N 4#define max 10struct product int

17、 id; /物品编号 int price;/物品价格 int weight;/物品重量 int flag;/物品标号 char name20;/物品名称PN;void math()/寻找最优组合的方法 int i,j,k;/定义三个循环变量,依次求出最大价值的物品组合及物品最大价值 int imax,jmaxa,jmaxb,kmaxa,kmaxb,kmaxc; int maxvalue1, maxvalue2, maxvalue3, maxvalue4; int maxnum; maxvalue1=0; imax=0; /第一次比较找出价值最大的商品,并把该商品价值赋给maxvalue1,商品

18、编号赋给maxi for(i=0;iN;i+) if(Pi.weightmaxvalue1) maxvalue1=Pi.price; imax=i; /从剩下的商品中找出较大价值,并存放在maxvalue2 maxvalue2=0; for(i=0;iN;i+) for(j=i+1;jN;j+) if(Pi.weight+Pj.weightmaxvalue2) maxvalue2=Pi.price+Pj.price; jmaxa=i; jmaxb=j; /从剩下的商品中找出较大价值,并存放在maxvalue3 maxvalue3=0; for(i=0;iN;i+) for(j=i+1;jN;j

19、+) for(k=i+2;kN;k+) if(Pi.weight+Pj.weight+Pk.weightmax) maxvalue3=Pi.price+Pj.price+Pk.price; kmaxa=i; kmaxb=j; kmaxc=k; /如果所有的物品总重量都小于背包能够承受的最大重量,则把所有物品放入背包 if(P0.weight+P1.weight+P2.weight+P3.weightmaxvalue1) maxnum=maxvalue2; if(maxvalue3maxnum) maxnum=maxvalue3; printf(%d,maxnum); if(maxnum=max

20、value1) printf(%d,maxnum); if(maxnum=maxvalue2) printf(%s,%d,%dn,Pjmaxa.name,Pjmaxa.weight,Pjmaxa.price); printf(%s,%d,%dn,Pjmaxb.name,Pjmaxb.weight,Pjmaxb.price); printf(%d,maxnum); system(pause);void scannum()/输入物品信息 int i=0; printf(t请输入物品信息(N=4):tn); for(i=0;iN;i+) Pi.id=i+1; printf(t物品名称: ); sca

21、nf(%s,&Pi.name); printf(t物品重量: ); scanf(%d,&Pi.weight); printf(t物品价格:); scanf(%d,&Pi.price); Pi.flag=0; printf(n); int main()/主函数,while循环变量选择你要进行的操作 int k; while(1) printf(请选择操作:n); printf(1.输入物品的信息n); printf(2.求取最佳方案n); scanf(%d,&k); switch (k) case 1:scannum();break;/调用scannum()方法完成物品信息的输入 case 2:

22、math(); break;/调用math()方法完成最佳组合及最大价值计算 default: return -1;/否则返回-1 system(cls);/CLS命令是清除屏幕上所有的文字 return 0;2.动态规划法求解01问题源程序:/动态规划法#include StdAfx.h#includeint c10100;/*对应每种情况的最大价值*/int knapsack(int m,int n) int i,j,w10,p10; printf(请输入每个物品的重量,价值:n); for(i=1;i=n;i+) scanf(%d,%d,&wi,&pi); for(i=0;i10;i+)

23、 for(j=0;j100;j+) cij=0;/*初始化数组*/ for(i=1;i=n;i+) for(j=1;j=m;j+) if(wici-1j) /*如果本物品的价值加上背包剩下的空间能放的物品的价值*/ /*大于上一次选择的最佳方案则更新cij*/ cij=pi+ci-1j-wi; else cij=ci-1j; else cij=ci-1j; return(cnm); int main() int m,n;int i,j; printf(请输入背包的承重量,物品的总个数:n); scanf(%d,%d,&m,&n); printf(旅行者背包能装的最大总价值为%d,knapsac

24、k(m,n); printf(n); return 0;3.贪心法求解01背包问题源程序#include stdafx.h#include #include typedef struct char name10; int weight; int price;Project;Project *Input(Project *wp,int TotalNum,int TotalWeight) int i,j,Way,GoBack,RealWeight,RealPrice,TotalPrice; Project temp; do printf(请选择:n); printf(1.空间最优n); print

25、f(2.价格最优n); printf(3.价格空间比最优n); scanf(%d,&Way); switch(Way) case 1:/选择空间最优 for(i=0;iTotalNum;i+) for(j=0;jwpj+1.weight) temp=wpj; wpj=wpj+1; wpj+1=temp; break; case 2:/选择价格最优 for(i=0;iTotalNum;i+) for(j=0;jwpj+1.price) temp=wpj; wpj=wpj+1; wpj+1=temp; break; case 3:/价格空间比最优 for(i=0;iTotalNum;i+) for(j=0;jTotalNum-i-1;j+) if(float)wpj.price/(float)wpj.w

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1