背包问题的三种解法代码实现.docx
- 文档编号:28991949
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:18
- 大小:100.31KB
背包问题的三种解法代码实现.docx
《背包问题的三种解法代码实现.docx》由会员分享,可在线阅读,更多相关《背包问题的三种解法代码实现.docx(18页珍藏版)》请在冰豆网上搜索。
背包问题的三种解法代码实现
背包问题的三种解法实验报告
实验要求:
分别用动态规划法、回溯法、分支限界法解决0/1背包问题,了解三种算法的算法步骤并上机实现。
实验步骤:
1.建立一个背包问题的解法类Bag.h。
bag_m为动态规划法,bag_b为回溯法,bag_t为分支限界法。
2.建立一个排序类Sort1.h。
程序的需要对背包的价值比排序。
3.由分支限界建立一个动态的最大堆及堆的各种操作和运算类SqList.h。
代码实现:
1.主函数:
//背包问题的解法
#include
#include"Bag.h"//背包问题处理方法类
usingnamespacestd;
intmain()
{
inti,n,M;
cout<<"请输入物品个数:
";
cin>>n;
double*m=newdouble[n+1];
double*p=newdouble[n+1];
cout<<"输入每个物品的重量:
";
for(i=1;i<=n;i++)
cin>>m[i];
cout<<"输入每个物品的价值:
";
for(i=1;i<=n;i++)
cin>>p[i];
cout<<"请输入背包的重量:
";
cin>>M;
Bagbag;//创建一个背包问题的解法类对象
cout<<"选择背包问题的解法,输入1,动态规划法,输入2,回溯法,输入3,分支限界法。
"<<'\n'<<"请输入1或者2,或者输入3:
"<<"";
cin>>i;
if(i==1)
bag.bag_m(m,p,n,M);//调用动态规划法
if(i==2)
bag.bag_b(m,p,n,M);//调用回溯法
if(i==3)
bag.bag_t(m,p,n,M);//调用分支限界法
return0;
}
2.排序方法类:
(Filename:
Sort1.h)
//合并排序类(合并排序)
#include
usingnamespacestd;
structobj
{
doublem;
doublep;
doublev;
};
typedefstructobjOBJ;//定义物体的数据结构
classSort1
{
public:
voidmerge_sort(OBJa[],intn)//以物体的价值比排序
{
inti,s,t=1;
while(t { s=t;t=2*s;i=0; while(i+t { merge(a,i,i+s-1,i+t-1,t); i=i+t; } if(i+s merge(a,i,i+s-1,n-1,n-i); } } voidmerge(OBJa[],intp,intq,intr,intn) { OBJ*bp=newOBJ[n]; inti,j,k; i=p;j=q+1;k=0; while(i<=q&&j<=r) { if(a[i].v<=a[j].v) bp[k++]=a[i++]; else bp[k++]=a[j++]; } if(i==q+1) { for(;j<=r;j++) bp[k++]=a[j]; } else { for(;i<=q;i++) bp[k++]=a[i]; } k=0; for(i=p;i<=r;i++) a[i]=bp[k++]; deletebp; } }; 3.背包问题解法类: (Filename: Bag.h) //背包问题方法类(包含三种方法) //bag_m动态规划法 //bag_b回溯法 //bag_t分支限界法 #include usingnamespacestd; #include"Sort1.h" #include"SqList.h" classBag { public: voidbag_m(double*m,double*p,intn,intM)//动态规划法 { inti,j; int*x=newint[n+1]; OBJ*objs=newOBJ[n+1]; objs[0].m=0; objs[0].p=0; objs[0].v=0; for(i=1;i<=n;i++) { objs[i].m=m[i]; objs[i].p=p[i]; objs[i].v=objs[i].m/objs[i].p; } double**optp; optp=newdouble*[n+1]; for(i=0;i { optp[i]=newdouble[M+1]; x[i]=0; } for(i=0;i<=n;i++) optp[i][0]=0; for(i=0;i<=M;i++) optp[0][i]=0; for(i=1;i<=n;i++) for(j=1;j<=M;j++) { if(objs[i].m>j) optp[i][j]=optp[i-1][j]; else { optp[i][j]=optp[i-1][j]; if(optp[i][j]<(optp[i-1][int(j-objs[i].m)]+objs[i].p)) optp[i][j]=(optp[i-1][int(j-objs[i].m)]+objs[i].p); } } i=n;j=M; while(i&&j) { if(optp[i][j]>optp[i-1][j]) { x[i]=1; j-=objs[i].m; } else x[i]=0; i--; } cout<<"输出结果,装入为1,不装入为0: "<<'\n'; for(i=1;i<=n;i++) cout< cout<<'\n'; cout<<"背包物体的总价值最大为: "< deletex,objs; for(i=0;i<=n;i++) delete[]optp[i]; deleteoptp; } voidbag_b(double*m,double*p,intn,intM)//回溯法 { inti,j,k; int*x=newint[n+1]; int*y=newint[n+2]; doublem_cur,m_est,p_cur,p_est,p_total; m_cur=0;p_cur=0;p_total=0; OBJ*objs=newOBJ[n+1]; objs[0].m=0; objs[0].p=0; objs[0].v=0; for(i=1;i<=n;i++) { objs[i].m=m[i]; objs[i].p=p[i]; objs[i].v=objs[i].m/objs[i].p; y[i]=0; x[i]=0; } y[n+1]=0; Sort1sort; sort.merge_sort(objs,n+1);//排序 k=1; while(k>=1) { p_est=p_cur;m_est=m_cur; for(i=k;i<=n;i++) { m_est=m_est+objs[i].m; if(m_est p_est=p_est+objs[i].p; else { p_est=p_est+((M-m_est+objs[i].m)/objs[i].m)*objs[i].p; break; } } if(p_est>p_total) { for(i=k;i<=n;i++) { if(m_cur+objs[i].m<=M) { m_cur+=objs[i].m; p_cur+=objs[i].p; y[i]=1; } else{y[i]=0;break;} } if(i>=n) { if(p_cur>p_total) { p_total=p_cur;k=n+1; for(j=1;j<=n;j++) x[j]=y[j]; } } elsek=i+1; } else { while(i>=1&&y[i]==0) i--; if(i<1)break; else { m_cur-=objs[i].m; p_cur-=objs[i].p; y[i]=0;k=i+1; } } } for(i=1;i<=n;i++) cout< cout<<'\n'; cout<<"total="< deletex,y,objs; } voidbag_t(double*m,double*p,intn,intM)//分支限界法 { inti; doublet; OBJ*ob=newOBJ[n]; for(i=0;i { ob[i].m=m[i+1]; ob[i].p=p[i+1]; ob[i].v=ob[i].m/ob[i].p; } Sort1sort; sort.merge_sort(ob,n); Knapnodekna,knax,knay;//定义左节点和右节点 kna.b=0;kna.k=0;kna.p=0;kna.w=0; for(i=0;i<5;i++) kna.s1[i]=0; for(i=kna.k,t=kna.w;i { if(t+ob[i].m<=M) { t+=ob[i].m; kna.b+=ob[i].p; } else { kna.b+=(M-t)*ob[i].p/ob[i].m; break; } } sqlistq; SqListsq; sq.InitList_Sq(q); sq.insert(q,kna); while(q.length! =0) { kna=sq.delete_max(q); if(kna.k==5) { cout<<"thevalueis: "< for(i=0;i<5;i++) cout< cout<<'\n'; break; } knay=kna; knay.k++;knay.b=knay.p; for(i=knay.k,t=knay.w;i { if(t+ob[i].m<=M) { t+=ob[i].m; knay.b+=ob[i].p; } else { knay.b+=(M-t)*ob[i].p/ob[i].m; break; } } sq.insert(q,knay); knax=kna; if(knax.w+ob[knax.k].m>M) continue; knax.s1[knax.k]=1; knax.w+=ob[knax.k].m; knax.p+=ob[knax.k].p; knax.k++; sq.insert(q,knax); } } }; 4.动态堆方法类(分支限界方法中用到,Filename: SqList.h) //动态最大堆 #include #include"math.h" #include usingnamespacestd; #defineListInitSize20 #defineListIncrement10 constn=5; typedefstruct { ints1[n]; intk; floatb; floatw; floatp; }Knapnode; typedefstructsqList { Knapnode*elem; intlength; intlistsize; }sqlist; classSqList//动态堆类 { public: voidInitList_Sq(sqlist&L)//n为单位元素的大小,初始化堆 { L.elem=(Knapnode*)malloc(ListInitSize*sizeof(Knapnode)); if(L.elem==NULL)exit(OVERFLOW); L.length=0; L.listsize=ListInitSize; } voidListInsert_Sq(sqlist&L,Knapnodeelem)//向堆中插入节点 { Knapnode*newbase; if(L.length>=L.listsize) { newbase=(Knapnode*)realloc(L.elem,(L.listsize+ListIncrement)*sizeof(Knapnode)); if(newbase==NULL)exit(OVERFLOW); L.elem=newbase; L.listsize+=ListIncrement; } L.elem[++L.length]=elem; } voidsift_up(sqlist&L,inti)//上移操作 { while(i>=2) if(L.elem[i].b>L.elem[i/2].b) { swap(L.elem[i/2],L.elem[i]); i/=2; } elsebreak; } voidsift_down(sqlist&L,inti)//下移操作 { intdone=0; i=2*i; while(done==0&&i<=L.length) { if(i+1<=L.length&&L.elem[i+1].b>L.elem[i].b) i++; if(L.elem[i/2].b swap(L.elem[i/2],L.elem[i]); elsedone=1; } } voidswap(Knapnode&a,Knapnode&b) { Knapnodet; t=a; a=b; b=t; } voidinsert(sqlist&L,Knapnodex)//插入节点后,并排序 { ListInsert_Sq(L,x); sift_up(L,L.length); } Knapnodedelete_max(sqlist&L)//删除堆中预测价值的最大者 { Knapnodep; p=L.elem[1]; swap(L.elem[1],L.elem[L.length]); L.length--; sift_down(L,1); returnp; } voidprint(sqlist&L)//打印堆的数据 { inti; for(i=1;i<=L.length;i++) cout< } }; 运行方法和结果(用这三种算法分别给出实验结果): 1.动态规划法: 2.回溯法: 3.分支限界法
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 背包 问题 解法 代码 实现