01背包问题不同算法设计分析与对比.docx
- 文档编号:12902674
- 上传时间:2023-04-22
- 格式:DOCX
- 页数:14
- 大小:17.99KB
01背包问题不同算法设计分析与对比.docx
《01背包问题不同算法设计分析与对比.docx》由会员分享,可在线阅读,更多相关《01背包问题不同算法设计分析与对比.docx(14页珍藏版)》请在冰豆网上搜索。
01背包问题不同算法设计分析与对比
实验三01背包问题不同算法设计、分析与对比
一.问题描述
给定n种物品和一背包。
物品i的重量是wi,其价值为vi,背包的容量为c。
问题:
应如何选择装入背包中的物品,使得装入背包中物品的总价值最大。
说明:
在选择装入背包的物品时,对每种物品i只有两个选择,装入背包或不装入背包,也不能将物品装入背包多次。
二.实验内容与要求
实验内容:
1.分析该问题适合采用哪些算法求解(包括近似解)。
动态规划、贪心、回溯和分支限界算法。
2.分别给出不同算法求解该问题的思想与算法设计,并进行算法复杂性分析。
动态规划:
递推方程:
m(i,j)=max{m(i-1,j),m(i-1,j-wi)+vi}j>=wi;
m(i-1,j)j 时间复杂度为O(n). 贪心法: 算法思想: 贪心原则为单位价值最大且重量最小,不超过背包最大承重量为约束条件。 也就是说,存在单位重量价值相等的两个包,则选取重量较小的那个背包。 但是,贪心法当在只有在解决物品可以分割的背包问题时是正确的。 贪心算法总是作出在当前看来最好的选择。 也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。 用贪心法设计算法的特点是一步一步地进行,根据某个优化测度(可能是目标函数,也可能不是目标函数),每一步上都要保证能获得局部最优解。 每一步只考虑一个数据,它的选取应满足局部优化条件。 若下一个数据与部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中, 直到把所有数据枚举完,或者不能再添加为止。 回溯法: 回溯法: 为了避免生成那些不可能产生最佳解的问题状态,要不断地利用限界函数(boundingfunction)来处死那些实际上不可能产生所需解的活结点,以减少问题的计算量。 这种具有限界函数的深度优先生成法称为回溯法。 对于有n种可选物品的0/1背包问题,其解空间由长度为n的0-1向量组成,可用子集数表示。 在搜索解空间树时,只要其左儿子结点是一个可行结点,搜索就进入左子树。 当右子树中有可能包含最优解时就进入右子树搜索。 时间复杂度为: O(2n) 空间复杂度为: O(n) 分支限界算法: 首先,要对输入数据进行预处理,将各物品依其单位重量价值从大到小进行排列。 在优先队列分支限界法中,节点的优先级由已装袋的物品价值加上剩下的最大单位重量价值的物品装满剩余容量的价值和。 算法首先检查当前扩展结点的左儿子结点的可行性。 如果该左儿子结点是可行结点,则将它加入到子集树和活结点优先队列中。 当前扩展结点的右儿子结点一定是可行结点,仅当右儿子结点满足上界约束时才将它加入子集树和活结点优先队列。 当扩展到叶节点时为问题的最优值。 3.设计并实现所设计的算法。 4.对比不同算法求解该问题的优劣。 这动态规划算法和贪心算法是用来分别解决不同类型的背包问题的,当一件背包物品可以分割的时候,使用贪心算法,按物品的单位体积的价值排序,从大到小取即可。 当一件背包物品不可分割的时候,(因为不可分割,所以就算按物品的单位体积的价值大的先取也不一定是最优解)此时使用贪心是不对的,应使用动态规划。 设计方法 时间复杂度 优点 缺点 动态规划 Min{nc,2n} 可求得最优决策序列 速度慢 贪心方法 O(2n) 速度较快 很难得到最优解 回溯法 O(n2n) 能够得到最优解 时间复杂度较高 分支限界法 O(2n) 速度较快,易求解 占用内存大,效率不高 5.需要提交不同算法的实现代码和总结报告。 动态规划方法: publicclassKnapsack{ publicstaticvoidmain(String[]args){ int[]value={0,60,100,120}; int[]weigh={0,10,20,30}; intweight=50; Knapsack1(weight,value,weigh); } publicstaticvoidKnapsack1(intweight,int[]value,int[]weigh){ int[]v=newint[value.length]; int[]w=newint[weigh.length]; int[][]c=newint[value.length][weight+1]; intd[]=newint[100]; for(inti=0;i v[i]=value[i]; w[i]=weigh[i]; } for(inti=1;i for(intk=1;k<=weight;k++){ if(w[i]<=k){ c[i][k]=max(c[i-1][k],c[i-1][k-w[i]]+v[i]); }else{ c[i][k]=c[i-1][k]; } } } System.out.println(c[value.length-1][weight]); } privatestaticintmax(inti,intj){ intk=i>j? i: j; returnk; } } 贪心法: publicclassGreedyKnapSack{ publicstaticvoidmain(String[]args){ int[]value={0,60,100,120}; int[]weigh={0,10,20,30}; intweight=50; Knapsack1(weight,value,weigh); } privatestaticvoidKnapsack1(intweight,int[]v,int[]w){ intn=v.length; double[]r=newdouble[n]; int[]index=newint[n]; for(inti=0;i r[i]=(double)v[i]/(double)w[i]; index[i]=i; } //按单位重量价值r[i]=v[i]/w[i]降序排列 doubletemp=0; for(inti=0;i for(intj=i+1;j if(r[i] temp=r[i]; r[i]=r[j]; r[j]=temp; intx=index[i]; index[i]=index[j]; index[j]=x; } } } //排序后的重量和价值分别存到w1[]和v1[]中 int[]w1=newint[n]; int[]v1=newint[n]; for(inti=0;i w1[i]=w[index[i]]; v1[i]=v[index[i]]; } System.out.println(Arrays.toString(w1)); System.out.println(Arrays.toString(v1)); ints=0;//包内现存货品的重量 intvalue=0;//包内现存货品总价值 for(inti=0;i if(s+w1[i] value+=v1[i]; s+=w1[i]; } } System.out.println("背包中物品的最大总价值为"+value); } } 回溯法: publicclassBacktrackKnapSack{ publicstaticvoidmain(String[]args){ int[]value={0,60,100,120}; int[]weigh={0,10,20,30}; intweight=50; Knapsack1(weight,value,weigh); } privatestaticvoidKnapsack1(intweight,int[]v,int[]w){ intn=v.length; double[]r=newdouble[n]; int[]index=newint[n]; for(inti=0;i r[i]=(double)v[i]/(double)w[i]; index[i]=i; } //按单位重量价值r[i]=v[i]/w[i]降序排列 doubletemp=0; for(inti=0;i for(intj=i+1;j if(r[i] temp=r[i]; r[i]=r[j]; r[j]=temp; intx=index[i]; index[i]=index[j]; index[j]=x; } } } //排序后的重量和价值分别存到w1[]和v1[]中 int[]w1=newint[n]; int[]v1=newint[n]; for(inti=0;i w1[i]=w[index[i]]; v1[i]=v[index[i]]; } //调用函数KnapSackBackTrack(),输出打印装完物品以后的最大价值 KnapSackBackTrack(w1,v1,w1.length,weight); } privatestaticvoidKnapSackBackTrack(int[]w1,int[]v1,intlength, intweight){ intCurrentWeight=0; intCurrentValue=0; intmaxValue=0; inti=0; intn=v1.length; while(i>=0){ if(CurrentWeight+w1[i] CurrentWeight+=w1[i]; CurrentValue+=v1[i]; i++; } else break; } if(i maxValue=CurrentValue; System.out.println("1背包中物品的最大总价值为"+maxValue); } } } 分支限界算法: packagebag01b; importjava.util.ArrayList; publicclassbag01do{ publicstaticvoidmain(String[]args){ //TODOAuto-generatedmethodstub ArrayList objects.add(newobject(10,60)); objects.add(newobject(20,100)); objects.add(newobject(30,120)); bagb=newbag(50,objects); b.findmaxvalue(); b.show(); } } ----------------------------------------------------------------------- packagebag01b; importjava.util.ArrayList; importjava.util.Collections; importjava.util.PriorityQueue; publicclassbag{ privateintbagv; privateArrayList privateintmaxvalue; privateArrayList publicbag(intv,ArrayList super(); this.bagv=v; this.objects=o; this.maxvalue=0; this.result_objects=null; Collections.sort(objects); } publicvoidshow(){ System.out.println("maxvalue: "+this.maxvalue); System.out.println("theobjectwhenmaxvalue: "+this.result_objects); } publicvoidfindmaxvalue(){ PriorityQueue Nodenode=newNode(0,null,bagv,this.objects); enode.offer(node); while(true){ if(enode.isEmpty()) break; node=enode.poll(); if(node.isend()){ this.maxvalue=node.get_bag_value(); this.result_objects=newArrayList<>(node.get_in_bag_object()); return; } inti=node.get_node_in(); objectiobject=this.objects.get(i); if(node.get_bag_weight()+iobject.getweight()<=this.bagv){ ArrayList newnodeinbag.add(iobject); intnewnodebagv=node.get_bag_leftv()-iobject.getweight(); Nodenewnode=newNode(i+1,newnodeinbag,newnodebagv,this.objects); enode.add(newnode); if(newnode.get_bag_value()>this.maxvalue){ this.maxvalue=newnode.get_bag_value(); this.result_objects=newArrayList<>(newnode.get_in_bag_object()); } } Nodenewnode=newNode(i+1,node.get_in_bag_object(),node.get_bag_leftv(),this.objects); if(newnode.get_bag_prio()>this.maxvalue) enode.add(newnode); } } } ----------------------------------------------------------------------- packagebag01b; importjava.util.ArrayList; publicclassNodeimplementsComparable privateintnode_in; privateArrayList privateArrayList privateintleftv; privateintprio; publicNode(inti,ArrayList super(); this.node_in=i; if(in==null) in=newArrayList<>(); this.inbag_object=in; this.leftv=l; this.outbag_object=out; this.prio=this.find_prio(); } privateintfind_prio(){ //TODOAuto-generatedmethodstub intbag_left=this.leftv; intp=this.get_bag_value(); inti=this.node_in; objectiobject=null; while(true){ if(i>=this.inbag_object.size()) break; iobject=this.inbag_object.get(i); if(iobject.getweight()>bag_left) break; bag_left-=iobject.getweight(); p+=iobject.getvalue(); i++; } if(i<=this.inbag_object.size()-1) p+=iobject.getvw()*bag_left; returnp; } publicintget_bag_weight(){ intw=0; for(objecto: this.inbag_object){ w+=o.getweight(); } returnw; } publicintget_bag_value(){ intw=0; for(objecto: this.inbag_object){ w+=o.getvalue(); } returnw; } @Override publicintcompareTo(Nodeo){ //TODOAuto-generatedmethodstub if(this.prio>o.prio)return-1; if(this.prio return0; } publicbooleanisend(){ if(this.node_in==this.outbag_object.size()) returntrue;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 01 背包 问题 不同 算法 设计 分析 对比