01背包问题实验报告.docx

上传人:b****5 文档编号:8134968 上传时间:2023-01-29 格式:DOCX 页数:11 大小:61.62KB
下载 相关 举报
01背包问题实验报告.docx_第1页
第1页 / 共11页
01背包问题实验报告.docx_第2页
第2页 / 共11页
01背包问题实验报告.docx_第3页
第3页 / 共11页
01背包问题实验报告.docx_第4页
第4页 / 共11页
01背包问题实验报告.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

01背包问题实验报告.docx

《01背包问题实验报告.docx》由会员分享,可在线阅读,更多相关《01背包问题实验报告.docx(11页珍藏版)》请在冰豆网上搜索。

01背包问题实验报告.docx

01背包问题实验报告

0-1背包问题实验报告

0-1背包问题实验报告小组成员:

姓名班级学号

贾倩楠201021130710211339

骆亮亮201021130710211318

高婧201021130810211370

一(算法设计名称:

0-1背包问题

二.实验内容

问题描述:

给定n种物品和一背包。

物品i的重量是w~其价值为v~背包ii的容量为C。

问应如何选择装入背包的物品~使得装入背包中物品的总价值最大?

在选择装入背包的物品时~对每种物品i只有两种选择~即装入背包或不装入背包。

不能将物品装入背包多次~也不能只装入部分的物品。

0-1背包问题是一个特殊的整数规划问题

nmaxvx,ii,1i

n,wx,C,,ii,,1i,x,{0,1},1,i,ni,

三.实验目的

1.运用动态规划思想~设计解决上述问题的算法~找出最大背包价值的装法。

2.掌握动态规划的应用。

四(算法:

问题求解思路

1.由0-1背包问题的最优子结构性质~建立计算m[i][j]的递归式如下:

j,wmax{m[i,1,j],m[i,1,j,w],v[i]},iim(i,j),,0,j,wm[i,1,j]i,

2.查找装入背包物品的函数:

从数组的最右下角开始寻找~如若m[i][weight]!

=

m[i-1][weight]~则该第i个物品就在背包中~将其从最大价值量中去掉~然后再接着寻找下一个在背包中的物品~直至i=0。

关键数据结构:

一个二维数组~两个一维数组~两个整型变量

intm[N+1][M+1]={0};//用于存储当前最好的价值量

intnumber,weight;//number表示物品的种类,weight表示背包重量的最大值

intw[N]={0},v[N]={0};//分别表示物品的重量和价值

函数摻块:

Main函数调用其余两个个函数完成算法:

voidknapsack(intnumber,intweight,int*w,int*v,intm[][M+1]);//整理背包函数,找出最大价值

voidfindobject(intnumber,intweight,int*w,int*v,intm[][M+1]);//找出所有在背包里的物品的函数

五(最终算法设计:

算法:

1.voidknapsack(intnumber,intweight,int*w,int*v,intm[][M+1]){//数组m[][],其横坐标row表示物品是第几个,纵坐标col表示当前背包中物品的重量从1到weight

introw,col;

for(row=1;row<=number;row++)

for(col=1;col<=weight;col++)

{

if(col>=w[row])//当背包重量大于第row个物品的重量时,再继续进行判断

{

-w[row]]+v[row]>m[row-1][col])if(m[row-1][col

m[row][col]=m[row-1][col-w[row]]+v[row];

else

1][col];//判断加入该第row个物品m[row][col]=m[row-

是否会增大价值量,若增大则加入,否则不加

}

else

m[row][col]=m[row-1][col];//如果背包重量小于w[row],则不加入任何物品,价值量不变

}

printf("Themostvalueoftheknapsackis:

%d.\n",m[number][weight]);//输出最大价值量

}

2.voidfindobject(intnumber,intweight,int*w,int*v,intm[][M+1]){

inti;

intx[N]={0};

for(i=number;i>0;i--)//从数组的最右下角开始找寻,直到找到最开始的m[0][]

{

if(m[i][weight]!

=m[i-1][weight])

{

x[i]=1;

weight=weight-w[i];//将找到的第i个物品从背包的重量中去掉

printf("%dthobjectischosen.weight:

%d,value:

%d\n",i,w[i],v[i]);//输出找到的物品的信息

}

}

}

六(运行结果:

当输入的数据不符合要求时:

七(分析时间复杂度:

n为物品总数~c为重量限制背包容量,

从m(i~j)的递归式容易看出~算法需要O(nc)计算时间。

当背

n包容量c很大时~算法需要的计算时间较多。

例如~当c>2时~算法

n需要Ω(n2)计算时间

八(改进算法:

算法思路:

1.由m(i,j)的递归式容易证明~在一般情况下~对每一个确定的i(1?

i?

n)~函数m(i,j)是关于变量j的阶梯状单调不减函数。

跳跃点是这一类函数的描述特征。

在一般情况下~函数m(i,j)由其全部跳跃点唯一确定。

如图所示。

对每一个确定的i(1?

i?

n)~用一个表p[i]存储其全部跳跃点。

初始时p[0]={(0~0)}~然后依次计算p[1],p[2]….p[n]

先将p[i]中可能包含的所有数对找出~然后再对其进行筛选~将不符合背包容量限制的~不符合最大价值量的数对删除~构成最终的p[i]跳跃点。

2.找背包中所装物品的方法和最初的算法类似~从最后装入的物品开始找起~若max与q[i].value[q[i].total-1]相等并且max不与q[i-1].value[q[i-1].total-1]相等~则说明第i个物品在背包中~输出相应的信息。

直至max=0。

数据类型:

structobject

{

intwei[N*2];

intvalue[N*2];

inttotal;

}p[20],q[20];//表示跳跃点集合的数据结构

intnumber,weight,max;//number表示物品的种类,weight表示背包重量的最大值,max表示装入背包最大的价值

intw[N]={0},v[N]={0};//分别表示物品的重量和价值

九(最终算法

1.voidknapsack(intnumber,intweight,int*w,int*v)

{//数组m[][],其横坐标row表示物品是第几个,纵坐标col表示当前背包中物品的重量从1到weight

inti,j,k,num;//i控制新的数据结构q的下标,j,k控制元素的比较,num控制结构q中各个数组元素的下标

intmax,all;//max表示最大价值

p[0].wei[0]=0;//将p[0],q[0]初始化为只含(0,0)的数据结构

p[0].value[0]=0;

p[0].total=1;

q[0].wei[0]=0;

q[0].value[0]=0;

q[0].total=1;

for(i=1;i<=number;i++)

{

p[i].total=q[i-1].total;

for(j=0;j

{

p[i].wei[j]=q[i-1].wei[j];

p[i].value[j]=q[i-1].value[j];

}//将上个跳跃点的所有数对先复制下来

for(k=0;k

{

if(q[i-1].wei[k]+w[i]<=weight)

{

p[i].wei[j]=q[i-1].wei[k]+w[i];

p[i].value[j]=q[i-1].value[k]+v[i];

p[i].total++;j++;

}//计算加入新的物品后的未超出限制重量的数对

}

//以上是计算每个跳跃点q[i]所含数对的个数并对其赋值

//之后是对q[i]目前的所有数对进行合并并删除,将其有序化

all=p[i].total;

for(num=0,j=0,k=p[i-1].total;j

{

if(p[i].wei[j]

{

if(p[i].value[j]<=p[i].value[k])

{

q[i].wei[num]=p[i].wei[j];

q[i].value[num]=p[i].value[j];

j++;num++;

}//总重量小并且价值小时,将其先放入q[i]中,num++

else

{

k++;p[i].total--;

}//总重量小单价值大时,将另一个删除,跳跃点所含数对数减1,再继续进行比较

}

elseif(p[i].wei[j]==p[i].wei[k])

{

if(p[i].value[j]

{

q[i].wei[num]=p[i].wei[k];

q[i].value[num]=p[i].value[k];//k价值大

}

else

{

q[i].wei[num]=p[i].wei[j];

q[i].value[num]=p[i].value[j];//j价值大

}

j++;k++;p[i].total--;num++;//总重量相等时,必定有个价值大的,将其写入p[i],另一个删除

}

else//j的总重量比k大时

{

if(p[i].value[j]>p[i].value[k])

{

q[i].wei[num]=p[i].wei[k];

q[i].value[num]=p[i].value[k];

k++;num++;

}//j的价值也比k大时,将k写入p[i],num++

else

{

j++;p[i].total--;

}//价值小的总重量大时,将其删除,再继续进行比较

}

}

q[i].total=p[i].total;

//下面将对剩余的没有排序的最后数对加入p[i]

while(j

{

if(p[i].value[j]

{

q[i].total--;

j++;

}//若j的价值比之前的最大的小。

则将其删除

else

{

q[i].wei[num]=p[i].wei[j];

q[i].value[num]=p[i].value[j];

j++;num++;

}//否则,将其加在之前填好p[i]的末尾

}

while(k

{

if(p[i].value[k]

{

q[i].total--;

k++;

}//若k的价值比之前的最大的小。

则将其删除

else

{

q[i].wei[num]=p[i].wei[k];

q[i].value[num]=p[i].value[k];

k++;num++;

}//否则,将其加在之前填好p[i]的末尾

}

}

max=q[i-1].value[q[i-1].total-1];

printf("Themostvalueoftheknapsackis:

%d.\n",max);//输出最大价值量

}

2.voidfindobject(intnumber,int*w,int*v){

inti,j;//控制循环

intmaxw,maxv;

maxw=q[number].wei[q[number].total-1];

maxv=q[number].value[q[number].total-1];

for(i=number;i>=0;i--)

{

for(j=q[i-1].total-1;j>=0;j--)

{

if((maxw-w[i])==q[i-1].wei[j]&&(maxv-v[i])==

q[i-1].value[j])

{//当某个物品所属行的最大价值量与之前的物品的不同时,该物品

即为装入包中物品

printf("%dthobjectischosen.

weight:

%d,value:

%d\n",i,w[i],v[i]);//输出找到的物品的信息

maxw=maxw-w[i];

maxv=maxv-v[i];//将去掉该物品后的最大价值量修改

break;

}

if(maxw==q[i-1].wei[j]&&maxv==q[i-1].value[j])

break;

}

}

}

十(运行结果

当输入的数据不符合要求时:

十一.分析时间复杂度

上述算法的主要计算量在于计算跳跃点集p[i](1?

i?

n)。

由于q[i+1]=p[i+1],(w~v)~故计算q[i+1]需要O(|p[i+1]|)计算时间。

ii

合并p[i+1]和q[i+1]并清除受控跳跃点也需要O(|p[i+1]|)计算时间。

从跳跃点集p[i]的定义可以看出~p[i]中的跳跃点相应于x,…,x的0/1赋值。

in

n-i+1因此~p[i]中跳跃点个数不超过2。

由此可见~算法计算跳跃

nn,,,,,nin,,O|p[i,1]|,O2,O2,,,,点集p[i]所花费的计算时间为,,,2,2ii,,,,

n从而~改进后算法的计算时间复杂性为O

(2)。

当所给物品的重量w(1?

i?

n)是整数时~|p[i]|?

c+1~(1?

i?

n)。

在这种情况下~改进后i

n算法的计算时间复杂性为O(min{nc,2})。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工作范文 > 行政公文

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

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