1、蛮力法动归贪心分支限界法解01背包问题算法综合实验报告学 号: 1004121206 姓 名: 林 一、实验内容:分别用蛮力、动态规划、贪心及分支限界法实现对0-1背包问题的求解,并至少用两个测试用例对所完成的代码进行正确性及效率关系上的验证。二、程序设计的基本思想、原理和算法描述:1、 蛮力法 1.1数据结构注:结构体obj用来存放单个物品的价值和重量 typedef struct obj int w;/物品的重量 int v;/物品的价值 ; 1.2 函数组成 void subset(int s10,int n):用来生成子集的函数 void judge(int s10, obj obj,
2、int mark,int n,int c):判断子集的可行性 int getmax(int mark,int n,int &flag):求解问题的最优解 void outputObj(int flag,int s10,int n):输出选择物品的情况 1.3 输入/输出设计 本程序通过键盘进行输入、屏幕进行输出。 1.4 符号名说明 符号 说明 S 存放子集 mark 记录子集的可行性 n 物品的个数 c 物品的容量 max 记录背包所能产生的最大价值 flag 记录能产生最大价值的子集的编号 1.5 算法描述 算法的伪代码描述如下: 输入:背包的容量c,物品的个数n,n个物品的重量 wn,价
3、值vn 输出:装入背包的物品编号以及产生的最大价值 1.初始化最大价值 max=0,结果子集 s=; 2.对集合1,2,.n的每一个子集T,执行下述操作: 2.1初始化背包的价值 v=0,背包的重量 w=0; 2.2对子集t的每一个元素j 2.2.1 如果w+wjc,则 w=w+wj,v=v+vj; 2.2.2 否则,转步骤2考察下一个子集; 2.3如果maxc) 4.1 将第i个物品放入背包,objecti.Num=1; 4.2 c-=pron.Weight; 4.3 i+;5.记录最后放入背包的物品的重量: objecti.Num=(double)C/objecti.Weight;4、 分
4、支限界法 4.1数据结构 注:物品结构体,存放物品价值、重量、单位价值、物品编号等信息 struct obj int v;/物品价值 int w;/物品重量 double avg;/物品单位价值 int id;/物品编号 ; 注:结构体node用来存放节点表节点 struct node node *parent,/父亲结点指针 *next;/后继结点指针 int level,/节点所处的层 isin,/记录物品是否装入背包,0代表不装,1代表装入 cw,/当前背包已经装入的物品重量 cv;/当前背包已经装入的物品价值 double ub;/结点的上界值 ; 4.2函数组成 int Partit
5、ion(_Object r,int first,int end);以数组第一个元素为准对数组进行一次划分并返回基准元素的位置坐标 void QuickSort(_Object r,int first,int end);快速排序 double Upb(int i,int cw,int cv);/计算上界值 node *nnoder(node * parent1,int isin1,double ub1);生成一个新的结点 void addnode(node *node1);/将结点添加到队列中 node *nextnode(); /取下一个结点 void fenzjx();/分支界限法的主要实现
6、函数 void output();/用于输出物品的选择情况及最优解4.3 输入/输出设计 本程序通过键盘进行输入、屏幕进行输出。 4.4 符号名说明 符号 说明 c 背包的容量 n 物品的个数 pro 存放物品信息 avg 物品的单位价值量 opv 背包容量最优解 popv 指向最优解的指针 level 节点的层 cw 当前背包装载量 cv 当前背包价值 ub 节点的上界值 isin 记录当前结点物品是否放入背包 flag 物品原来位置(4)算法描述 算法的伪代码描述如下: 输入:背包的容量c,物品的个数n,n个物品的信息 pron 输出:装入背包的物品标号和背包获得的最大价值 1.对输入的物
7、品按照单位价值量递减的顺序进行排序 2.初始化问题最优解opv=0,初始化第0层结点,计算上界值 ub=Upb(0,0,0);并设置该结点设为优先级队列的根结点 3.循环直到优先级队列为空 3.1 如果取出当前结点位于第n-1层,则其子结点已是叶子结点,判断子结点取值情况,若得到的解大于当前问题得到的最优解opv,则重置问题的最优解opv 3.2 如果取出当前结点层 level n-1 对结点i的每个孩子结点x执行下列操作: 3.2.1 如果结点x可能产生的最优解ubopv,则丢弃该结点; 3.2.2 否则估算该节点x的目标函数值ub,将结点加入队列; 4.将该结点对应的最优值输出,回溯求得最
8、优解的各个分量三、源程序及注释: 1、蛮力法#include#includeusing namespace std;/物品typedef struct obj int w; int v;/生成子集void subset(int s10,int n) int i,j,m,k; for(i=0;i=0;j-) m=k%2; sij=m; k=k/2; /判断子集可行性void judge(int s10, obj obj,int mark,int n,int c) int i,j,v,w; for(i=0;ipow(2,n);i+) w=0; v=0; for(j=0;jn;j+) w+=objj
9、.w*sij; v+=objj.v*sij; if(w=c) marki=v; else marki=0; /求问题的最优解int getmax(int mark,int n,int &flag) int i,max; max=0; for(i=0;imax) max=marki; flag=i; return max;/输出选择物品的情况void outputObj(int flag,int s10,int n) cout装入背包物品的编号为: ; for(int i=0;in;i+) if(sflagi=1) couti+1 ; coutendl;int main() int s10241
10、0,mark1024,n,max,c,flag; obj obj10; coutc; coutn; cout请分别输入物品的重量:; for(int i=0;iobji.w; cout请分别输入物品的价值:; for(i=0;iobji.v; subset(s,n); judge(s,obj,mark,n,c); max=getmax(mark,n,flag); outputObj(flag,s,n); cout背包可容纳的最大价值为: maxendl; return 0; 2、动态规划法#includeusing namespace std;/比较并返回两个数中的较大值int max(int
11、 i,int j) if(ij) return j; else return i;/求解背包取得的最大值int KnapSack (int w,int v,int x,int n,int c) int i,j,V1051005=0; for(i=0;i=n;i+) /初始化第0列 Vi0=0; for(j=0;j=c;j+) /初始化第0行 V0j=0; for(i=1;i=n;i+) /计算第i行,进行第i次迭代 for(j=1;j=c;j+) if(j0;i-) /求装入背包的物品编号 if(VijVi-1j) xi=1; j=j-wi; else xi=0; return Vnc;int
12、 main() int c,n,w105,v105,x105,max;/x记录物品的选择情况 coutc; coutn; cout请分别输入物品的重量:; for(int i=1;iwi; cout请分别输入物品的价值:; for( i=1;ivi; max=KnapSack(w,v,x,n,c); cout装入背包的物品编号为:; for(i=1;i=n;i+) if(xi=1) couti ; coutendl; cout背包可容纳的最大价值为:maxendl; return 0; 3、贪心法#include#includeusing namespace std;/物品结构体struct
13、_Object int Value;/物品价值 int Weight;/物品重量 double AveValue;/物品单位价值 double Num;/物品可以放入的数量 int key;/物品标号;/划分int Partition(_Object r,int first,int end) int i=first,j=end; while(ij) while(irj.AveValue) j-; if(ij) _Object temp=ri; ri=rj; rj=temp; i+; while(irj.AveValue) i+; if(ij) _Object temp=ri; ri=rj; r
14、j=temp; j-; return i;/快速排序void QuickSort(_Object r,int first,int end) int pivot; if(firstend) pivot=Partition(r,first,end); QuickSort(r,first,pivot-1); QuickSort(r,pivot+1,end); double knaspsack(int n,int M,_Object object) /n为物品个数,M为背包容量 int i; int C=M; double maxValue=0; for(i=0;objecti.WeightC;i+)
15、 objecti.Num=1;/初始化放入背包的物品为0 maxValue+=objecti.Value; C=C-objecti.Weight; objecti.Num=(double)C/objecti.Weight; maxValue+=objecti.Num*objecti.Value; return maxValue;int main() int n,c; _Object pro1001; coutc; coutn; cout请分别输入物品的重量和价值:;for(int i=0;iproi.Weightproi.Value; proi.AveValue=(double)proi.Va
16、lue/proi.Weight; proi.Num=0; proi.key=i; QuickSort(pro,0,n-1); double maxValue=knaspsack(n,c,pro); cout背包的可容纳的最大价值为:; printf(%.2f,maxValue); coutendl; int k; cout各个物品装入背包的重量分别为:; for(k=0;kn;k+) for(int j=0;jn;j+) if(proj.key=k) /找到原来顺序的物品编号 coutproj.Weight*proj.Num ; coutendl; return 0; 4、分支限界法 #inc
17、lude #include #include #include #include using namespace std;/物品结构体struct obj int v;/物品价值 int w;/物品重量 double avg;/物品单位价值 int id;/物品编号;/节点结构体struct node node *parent,/父亲结点指针 *next;/后继结点指针 int level,/节点所处的层 isin,/记录物品是否装入背包,0代表不装,1代表装入 cw,/当前背包已经装入的物品重量 cv;/当前背包已经装入的物品价值 double ub;/结点的上界值;/划分int Parti
18、tion(obj r,int first,int end) int i=first,j=end; while(ij) while(irj.avg) j-; if(ij) obj temp=ri; ri=rj; rj=temp; i+; while(irj.avg) i+; if(ij) obj temp=ri; ri=rj; rj=temp; j-; return i;/快速排序void QuickSort(obj r,int first,int end) int pivot; if(firstend) pivot=Partition(r,first,end); QuickSort(r,fir
19、st,pivot-1); QuickSort(r,pivot+1,end); class fzjxprivate: node *front,/队首指针 *first,/根节点指针 *popv;/解结点指针 double opv;/背包可产生的最大价值 obj *pro;/物品 int n,/物品个数 c;/背包容量public: fzjx(obj *pro1,int w1,int n1 ); fzjx(); int *flag; double Upb(int i,int cw,int cv);/计算上界值 node *nnoder(node * parent1,int isin1,double
20、 ub1); void addnode(node *node1);/将结点添加到队列中 node *nextnode(); /取下一个结点 void fenzjx(); void output();fzjx:fzjx(obj *pro1,int c1,int n1 ) int i; n=n1;c=c1; pro=new obj n; flag=new intn; for(i=0;inext=NULL; opv=0; popv=new node1; popv=NULL; QuickSort(pro,0,n-1);fzjx:fzjx() deletefirst; deletefront; deletepopv; deletepro;double fzjx:Upb(int i,int cw,int cv) int cleft=c-cw; double v=(double)cv; if (iparent=parent1; node2
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1