综合设计性实验报告背包问题的多种算法设计与分析文档格式.docx
- 文档编号:18507342
- 上传时间:2022-12-18
- 格式:DOCX
- 页数:11
- 大小:19.57KB
综合设计性实验报告背包问题的多种算法设计与分析文档格式.docx
《综合设计性实验报告背包问题的多种算法设计与分析文档格式.docx》由会员分享,可在线阅读,更多相关《综合设计性实验报告背包问题的多种算法设计与分析文档格式.docx(11页珍藏版)》请在冰豆网上搜索。
按照物品价值v[i]/w[i]由高到低对v[o..n]和w[0..n]进行排序。
然后把物品从1到n依次加入背包,直到装不下为止。
设c为背包容量,每次装一个物品,则c-=w[i],当前价值为value+=v[i],当c<
=0时,停止加入物品,现在的value即为最优值。
对于背包问题,贪婪选择最终可取得最优解,但对于0-1背包问题,贪婪选择无法保证最终能将背包装满,部份闲置的背包空间使单位背包空间的价值降低了。
2.递归求解
1)0-1背包最优问题具有最优子结构性质。
设(y1,y2,...,yn)是所给0-1背包的一个最优解,则(y2,y3,...,yn)是除y1外的最优解。
2)设所给0-1背包问题的子问题的最优值为m(i,j),即m(i,j)是背包容量为j,可选物品为i,i+1,...,n时0-1背包问题的最优值。
由0-1背包的问题的最优子结构性质,能够成立计算m(i,j)的递归式如下:
m(i,j)=max{m(i+1,j),m(i+1,j-wi)+vi}j>
=wi
=m(i+1,j)0<
=j<
wi
m(i,j)=vnj>
=wn
=00<
wn
用二维数组m[i][j]存储m(i,j)的值。
按照递归式算出m[i][j]的值。
则m[1][c]是给出所要求的0-1背包问题的最优值。
相应的最优解可由算法Traceback计算如下。
若是m[1][c]=m[2][c],则x1=0,不然x1=1.当x1=0时,由m[2][c]继续构造最优解。
当x1=1时,由m[2][c]继续构造最优解。
当x1=1时,由m[2][c-w1]继续构造最优解。
依次类推,可构造出相应的最优解(x1,x2,...,xn)。
voidTraceback(int**m,intn,int*w,intc,int*x)
{
inti;
if(m[1][c]==m[2][c])
x[1]=0;
elsex[1]=1;
for(i=1;
i<
=n-2;
i++)
{
if(x[i]==1)
c-=w[i];
if(m[i+1][c]==m[i+2][c])
x[i+1]=0;
elsex[i+1]=1;
}
if(m[n][c]!
=0)
x[n]=1;
}
3.动态计划
基于递归式的讨论,用二维数组m[][]来存储m(i,j)的相应值,可设计解0-1背包问题的动态计划算法Knapsack如下:
template<
classType>
voidKnapsack(Type*v,int*w,intc,intn,Type**m)
intjMax=min(w[n]-1,c);
for(intj=0;
j<
=jMax;
j++)m[n][j]=0;
for(j=w[n];
=c;
j++)m[n][j]=v[n];
for(inti=n-1;
i>
1;
i--){
jMax=min(w[i]-1,c);
for(j=0;
j++)m[i][j]=m[i+1][j];
for(j=w[i];
j++)m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
m[1][c]=m[2][c];
if(c>
=w[1])m[1][c]=max(m[1][c],m[2][c-w[1]]+v[1]);
template<
voidTraceback(Type**m,int*w,intc,intn,int*x)
fpr(inti=1;
n;
if(m[i][c]==m[i+1][c])x[i]=0;
else{x[i]=1;
c-=w[i];
x[n]=(m[n][c])?
1:
0;
4.回溯法求解
0-1背包问题是子集选取问题。
一般情形下,0-1背包问题是NP难的。
0-1背包问题的解空间可用子集树表示。
在搜索解空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左子树。
当右子树中有可能包括最优解时才进入右子树搜索。
不然将右子树剪去。
设r是当前剩余物品价值总和;
cp是当前价值;
bestp是当前最优价值。
计算右子树上界的方式是将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下去时,再装入该物品的一部份而装满背包。
由此取得的价值是右子树中解的上界。
为了计算上界,可先将物品依其单位重量价值从小到大排序,尔后只要按顺序考察各物品即可。
将物品依其单位价值排序的算法如下:
classObject{
friendintKnapsack(int*,int*,int,int,int*);
friendvoidSort(Object*,int);
public:
intoperator<
=(Objecta)const
{return(d>
=;
private:
intID;
floatd;
n]来记录最优解,在Backtrack算法中回溯取得bestx,当取得第一个最优值,若后面回溯到叶结点时值不大于当前最优值,则最优解bestx不改变。
Backtrack中取得最优值和最优解的算法如下:
classTypew,classTypep>
voidKnap<
Typew,Typep>
:
Backtrack(inti)
intflag;
if(i>
n){归求解
在编写递归的算法,最关键的就是如何用二维数组来表示相应最优解的值,编写的时候需要注意传值。
思路清楚,把数学的递归式用代码函数表示出来。
对于递归求解,算法简单,但消耗时刻太长。
在数据较少的情形下,能够专门快取得正确结果,当数据达到35个数据的时候,需要较长时刻,当数据达到40个以上的时候,由于时刻太长则等待不出结果。
可见递归的效率很低。
针对递归算法效率较低,可采用动态计划进行改良。
采用动态计划算法,效率较高。
用所提供的数据测试,均能专门快得出正确结果。
在编写动态计划算法时,没有太大问题,只需要编写求出最大值和最小值的函数。
还有回溯求最优解的算法。
在编写该算法时第一碰到的第一个问题是要运用C++的一些语法,这对于只懂C的同窗确实存在一下障碍。
好在咱们的小组成员有些人之前学过,所以在这方面问题不大,再加上不懂时通过网上查阅资料和相关书籍,问题专门快就取得解决。
另外,就是在Backtrack算法中求出最优值和最优解,每次当剩余的价值大于bestp,则进入右子树进行搜索。
当抵达叶结点时即取得一个最优值,把值赋给bestp,取得新的最优值。
同时需记录最优解,现在把记录路径的数组x[1..n]的值赋给bestx[1..n]。
在记录最优解时需要注意一个问题。
因为回溯的顺序是依照物品单位价值从高到低的顺序进行的,而输出的最优解则需要依照原顺序输出。
所以在回溯中记录路径时,需注意记录的是原来顺序下的路径,而不是排序后的路径。
在这里咱们在排序之前已经概念好一个类Q。
类中的数据成员ID用来记录物品原来的位置。
则排序后,物品原来的位置记录仍能被找到。
则搜索到某个结点时,则x[ID[i]]=1,不然x[ID[i]]=0.
5.分支界限法
分支限界法的与回溯法不同的是前者是深度优先搜索,后者是广度优先搜索。
分支限界法的效率会高些,可是需要成立一个最大堆作为优先队列。
概念一个类MaxHeap来实现优先队列,概念如下:
classT>
classMaxHeap
public:
MaxHeap(Ta[],intsize,intmaxsize=50);
MaxHeap(intmaxsize=50);
virtual~MaxHeap();
voidInitialize(Tarrays[],intsize,intarray_size);
心算法
否
--
是
40+
3.动态规划
4.回溯法
5.分支限界法
五、附录多种算法实现清单:
带注释和功能模块说明的源程序清单:
#include<
iostream>
usingnamespacestd;
voidsort2(intn,int*v,int*w,int*&
sort)
inti,j,temp;
for(i=2;
=n;
for(j=1;
=i;
j++)
if(v[sort[i]]/w[i]<
v[sort[j]]/w[j])
{
temp=sort[i];
sort[i]=sort[j];
sort[j]=temp;
}
intGreedy(intn,int*w,int*v,int*&
x,intc,int*sort)
inti,value=0;
for(i=n;
=1;
i--)
c-=w[sort[i]];
if(c>
{x[sort[i]]=1;
value+=v[sort[i]];
elsebreak;
returnvalue;
intmain()
intn,c,i,value;
FILE*fp;
FILE*ptr;
int*x,*w,*v,*sort;
fp=fopen("
D:
\\"
"
r"
);
归求解
intma(inti,intj,intn,int**&
m,int*w,int*v)
inta,b,value;
if(i==n)
if(j>
=w[n])
value=v[n];
elsevalue=0;
returnvalue;
if(i<
n)
{if(j>
=w[i])
m[i+1][j]=ma(i+1,j,n,m,w,v);
a=m[i+1][j];
m[i+1][j-w[i]]=ma(i+1,j-w[i],n,m,w,v);
溯法求解
classKnap{
friendTypepKnapsack(Typep*,Typew*,Typew,int,int*);
private:
TypepBound(inti);
voidBacktrack(inti);
Typewc;
<
Q[j-1].d)
temp=Q[i-1].ID;
Q[i-1].ID=Q[j-1].ID;
Q[j-1].ID=temp;
*/
TypepKnapsack(Typepp[],Typeww[],Typewc,intn,int*x)
{D=i;
Q[i-1].d=*p[i]/w[i];
P+=p[i];
W+=w[i];
if(W<
=c)returnP;
D];
[i]=w[Q[i-1].ID];
[i]=Q[i-1].ID;
[i]=0;
=0;
=c;
=n;
支界限法
algorithm>
#ifndefMAXHEAP_H
#defineMAXHEAP_H
template<
endl;
throwexception("
堆空间已满"
Data[++CurrentSize]=value;
ModifyUp(CurrentSize);
堆空"
value=Data[1];
Data[1]=Data[CurrentSize--];
ModifyDown(1,CurrentSize);
D=i;
j-1].ID]=[j];
delete[]Q;
delete[];
deltet[];
returnbestp;
int*x,*w,*v;
fp=fopen("
if(!
fp)
printf("
filecannotbeopened"
exit
(1);
fscanf(fp,"
%Ld%Ld"
&
c,&
n);
x=newint[n+1];
w=newint[n+1];
v=newint[n+1];
for(i=1;
x[i]=0;
fscanf(fp,"
w[i],&
v[i]);
value=Knapsack(v,w,c,n,x);
//cout<
value<
/*intva=0;
if(x[i])
va+=v[i];
cout<
va<
ptr=fopen("
"
w"
fprintf(ptr,"
%d\n"
value);
%d%d\n"
i,x[i]);
fclose(fp);
fclose(ptr);
return0;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 综合 设计 实验 报告 背包 问题 多种 算法 分析