实验3物联1301班刘悦08080112.docx
- 文档编号:7633154
- 上传时间:2023-01-25
- 格式:DOCX
- 页数:15
- 大小:190.79KB
实验3物联1301班刘悦08080112.docx
《实验3物联1301班刘悦08080112.docx》由会员分享,可在线阅读,更多相关《实验3物联1301班刘悦08080112.docx(15页珍藏版)》请在冰豆网上搜索。
实验3物联1301班刘悦08080112
算法分析与设计实验报告
第3次实验
姓名
刘悦
学号
201308080112
班级
物联1301班
时间
11.14上午
地点
工训楼C栋309
实验名称
动态规划法求解背包问题
实验目的
通过上机实验,要求掌握动态规划算法的问题描述、算法设计思想、程序设计。
实验原理
实验步骤
1把问题分解成若干子问题。
2依次求解出各个子问题的最优解。
3每个子问题的最优解又可以从它的子问题的最优解中得到。
4通过各个子问题的最优解得到原问题的最优解。
关键代码
/*=================================================================
min函数是求最小值的函数。
输入两个整型数x,y。
返回两个整型数中x,y中较小的一个。
=================================================================*/
intmin(intx,inty)
{
returnx>y?
y:
x;
}
/*=================================================================
max函数是求最大值的函数。
输入两个整型数x,y。
返回两个整型数中x,y中较大的一个。
=================================================================*/
intmax(intx,inty)
{
returnx>y?
x:
y;
}
/*=================================================================
Traceback函数是用来确定物品是否装入背包中的函数。
根据m数组,比较m[i][c-之前装入背包的重量]与m[i+1][c-之前装入背包的重量]的值是否相等,
若相等,则x[i]=0,即物品i不装入背包中;否则x[i]=1,代表物品i装入背包中。
*******************************************************************
c表示背包可容纳的容量。
n表示可选放入背包的物品的个数。
w[i]表示第i个物品的重量,大小为n。
v[i]表示第i个物品的价值,大小为n。
m[i][j]表示背包容量为j时,i个物品导致的最优解的总价值。
x[i]表示第i个物品是否放入背包,0代表不放入背包,1代表放入背包。
=================================================================*/
voidTraceback(intc,intn,intw[],int**m,intx[])
{
for(inti=1;i 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; } /*================================================================= Knapsack函数是用动态规划求解。 从最后一个物品开始,然后求前n-1,n-2…… 然后就开始填充矩阵,若背包剩余容量小于物品的重量,则将下面一行已填好的直接移动到这里。 若背包剩余容量大于物品的重量,则为m[i+1][j]和m[i+1][j-w[i]]+v[i]中的最大值。 ******************************************************************* c表示背包可容纳的容量。 n表示可选放入背包的物品的个数。 w[i]表示第i个物品的重量,大小为n。 v[i]表示第i个物品的价值,大小为n。 m[i][j]表示背包容量为j时,i个物品导致的最优解的总价值。 m[1][c]表示放入背包的物品的最大价值。 =================================================================*/ voidKnapsack(intc,intn,intw[],intv[],int**m) { intjMax=min(w[n]-1,c); for(intj=0;j<=jMax;j++)//0<=j m[n][j]=0; for(intj=w[n];j<=c;j++)//wn<=j的时候m[n][j]=vn m[n][j]=v[n]; for(inti=n-1;i>1;i--) { jMax=min(w[i]-1,c); for(intj=0;j<=jMax;j++)//0<=j m[i][j]=m[i+1][j]; for(intj=w[i];j<=c;j++) //wn<=j的时候m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]) //这里需要看将此物品加入背包与不加入背包哪个产生的价值更大些。 m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]); } m[1][c]=m[2][c];//m[1][c]的赋值 if(c>=w[1]) m[1][c]=max(m[1][c],m[2][c-w[1]]+v[1]); } 测试结果 1首先需要验证函数的编写是否正确,故使用一组可人为判断结果是否正确的数据进行测量。 给定背包重量为8,可放入物品共4件,为物品(w,v)={(1,2),(4,1),(2,4),(3,3)},计算之后第1、3、4件物品需装入,第2件物品不装入。 程序运行结果如下,可以知道结果正确。 2然后进行多组数据比较测试,这里选取了10组数据进行测试,10组数据是随机生成的,设置为每个随机数均小于等于100,测试结果如下。 3由上面的结果可以看出,不管是大数据还是小数据的时候,此算法的性能都较好,所用时间都比较小。 实验心得 这个实验因为书上有实现代码,所以其实写的没有那么纠结。 觉得不太好的地方,就是多组数据测试和大数据的测试。 因为大数据的时候我选择使用随机数来实现,所以这里就存在一个问题,不能确定得到的结果是否正确。 为了保证我们的函数实现是正确的,并进行多组数据测试,选择大数据小数据,使用以下方法来实现: 写两个main函数,每次执行一个而将另一个注释掉。 其中一个是一组小的数据,提前自己计算求得结果,然后验证函数实现是否正确。 另外一个就是多组数据,既包含大数据也包含小数据,每次只输出放入背包的物品的编号。 因为多组数据主要是看多组数据的函数执行时间进行比较,所以上面的方法我认为完全是可以的。 但比较麻烦的一点就是每次都要去注释到另外一个才可以执行。 动态规划本来就不好理解,通过这次实验,掌握了动态规划,相信在以后一定可以更加熟练的使用动态规划。 完善方向: 这里的动态规划实现0-1背包问题,只是实现了物品的重量和价值是整型数的时候,以后可进一步实现重量和价值不是整型数的函数编写。 实验得分 助教签名 附录: 完整代码 #include #include #include #include usingnamespacestd; intv[9999999]; intw[9999999]; intx[9999999]; /*============================================================================ ran函数是产生随机数的函数,数的范围设置为0-100。 此函数用于大数据测试时产生数据以供使用。 输入为数组a和数组大小n, 即产生大小为n的数组a[n],数组内存放的为随机数。 无返回值。 ============================================================================*/ voidran(int*a,intn) { inti; srand(time(0)); for(i=0;i a[i]=rand()%101; a[i]='\0'; } /*============================================================================ min函数是求最小值的函数。 输入两个整型数x,y。 返回两个整型数中x,y中较小的一个。 ============================================================================*/ intmin(intx,inty) { returnx>y? y: x; } /*============================================================================ max函数是求最大值的函数。 输入两个整型数x,y。 返回两个整型数中x,y中较大的一个。 ============================================================================*/ intmax(intx,inty) { returnx>y? x: y; } /*============================================================================ Traceback函数是用来确定物品是否装入背包中的函数。 根据m数组,比较m[i][c-之前装入背包的重量]与m[i+1][c-之前装入背包的重量]的值是否相等, 若相等,则x[i]=0,即物品i不装入背包中;否则x[i]=1,代表物品i装入背包中。 ****************************************************************************** c表示背包可容纳的容量。 n表示可选放入背包的物品的个数。 w[i]表示第i个物品的重量,大小为n。 v[i]表示第i个物品的价值,大小为n。 m[i][j]表示背包容量为j时,i个物品导致的最优解的总价值。 x[i]表示第i个物品是否放入背包,0代表不放入背包,1代表放入背包。 ============================================================================*/ voidTraceback(intc,intn,intw[],int**m,intx[]) { for(inti=1;i 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; } /*============================================================================ Knapsack函数是用动态规划求解。 从最后一个物品开始,然后求前n-1,n-2…… 然后就开始填充矩阵,若背包剩余容量小于物品的重量,则将下面一行已填好的直接移动到这里。 若背包剩余容量大于物品的重量,则为m[i+1][j]和m[i+1][j-w[i]]+v[i]中的最大值。 ****************************************************************************** c表示背包可容纳的容量。 n表示可选放入背包的物品的个数。 w[i]表示第i个物品的重量,大小为n。 v[i]表示第i个物品的价值,大小为n。 m[i][j]表示背包容量为j时,i个物品导致的最优解的总价值。 m[1][c]表示放入背包的物品的最大价值。 ============================================================================*/ voidKnapsack(intc,intn,intw[],intv[],int**m) { intjMax=min(w[n]-1,c); for(intj=0;j<=jMax;j++)//0<=j m[n][j]=0; for(intj=w[n];j<=c;j++)//wn<=j的时候m[n][j]=vn m[n][j]=v[n]; for(inti=n-1;i>1;i--) { jMax=min(w[i]-1,c); for(intj=0;j<=jMax;j++)//0<=j m[i][j]=m[i+1][j]; for(intj=w[i];j<=c;j++) //wn<=j的时候m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]) //这里需要看将此物品加入背包与不加入背包哪个产生的价值更大些。 m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]); } m[1][c]=m[2][c];//m[1][c]的赋值 if(c>=w[1]) m[1][c]=max(m[1][c],m[2][c-w[1]]+v[1]); } /*============================================================================ main函数(可选)是主函数。 实现输入输出来调用之前的动态规划函数和确定是否装入函数。 这个主函数是为了测试多组数据,所以使用随机数产生数据。 一共生成5组测试数据,包括大数据和小数据。 ****************************************************************************** c表示背包可容纳的容量。 n表示可选放入背包的物品的个数。 w[i]表示第i个物品的重量,大小为n。 v[i]表示第i个物品的价值,大小为n。 m[i][j]表示背包容量为j时,i个物品导致的最优解的总价值。 x[i]表示第i个物品是否放入背包,0代表不放入背包,1代表放入背包。 m[1][c]表示放入背包的物品的最大价值。 ============================================================================*/ /*intmain() { intc[6]={2,10,100,999,99,9998}; intn[6]={9,100,100,99,999,999}; inti,j; cout<<"---------------------动态规划--------------------------"< for(i=0;i<6;i++) { int**m; intnum=1; m=newint*[max(c[i],n[i])+1]; for(intj=0;j<=max(c[i],n[i]);j++) m[j]=newint[max(c[i],n[i])+1]; //调用ran函数来生成随机数初始化数组v和w ran(v,n[i]); ran(w,n[i]); clock_tstart,end,over; start=clock(); end=clock(); over=end-start; start=clock(); Knapsack(c[i],n[i],w,v,m); Traceback(c[i],n[i],w,m,x); end=clock(); cout<<"待选物品数量: "< cout<<"背包可容纳重量: "< cout<<"放入背包的总价值: "< cout<<"放入背包的物品的编号: "< for(intj=1;j<=n[i];j++) { if(x[j]==1) { cout< num++; } if(num%10==0) cout< } if(num==1) cout<<"无"; num=1; printf("\nThetimeis%6.3f\n",(double)(end-start-over)/CLK_TCK); cout<<"-------------------------------------------------------"< //释放动态申请的二维数组的内存 for(intj=0;j<=max(n[i],c[i]);j++) delete[]m[j]; delete[]m; } return0; }*/ /*============================================================================ main函数(可选)是主函数。 实现输入输出来调用之前的动态规划函数和确定是否装入函数。 这个主函数是为了单组数据,用来检测调用函数是否有问题。 用来验证结果的正确性,这里选用一组可人为判断的数据进行验证。 ******************************************************************************** c表示背包可容纳的容量。 n表示可选放入背包的物品的个数。 w[i]表示第i个物品的重量,大小为n。 v[i]表示第i个物品的价值,大小为n。 m[i][j]表示背包容量为j时,i个物品导致的最优解的总价值。 x[i]表示第i个物品是否放入背包,0代表不放入背包,1代表放入背包。 m[1][c]表示放入背包的物品的最大价值。 ============================================================================*/ intmain() { intn=4; intc=8; inttemp=0; intv[6]={0,2,1,4,3}; intw[6]={0,1,4,2,3}; intx[6]={0,0,0,0,0}; int**m; m=newint*[n+1]; for(inti=0;i<=n;i++) m[i]=newint[c+1]; for(inti=0;i<=n;i++) for(intj=0;j<=c;j++) m[i][j]=0; clock_tstart,end,over; start=clock(); end=clock(); over=end-start; start=clock(); Knapsack(c,n,w,v,m);//调用函数动态规划求解 Traceback(c,n,w,m,x);//调用函数确定物品是否装入背包 end=clock(); cout<<"------------动态规划------------"< cout<<"待选物品数量: "< cout<<"背包可容纳重量: "< cout<<"--------------------------------"< cout<<"计算过程中的矩阵: "< for(inti=1;i<=4;i++) { for(intj=1;j<=8;j++) cout< cout< } cout<<"--------------------------------"< cout<<"编号\t价值\t重量\t是否装入"< for(inti=1;i<=n;i++) { //循环打印出物品的编号、价值、重量和是否装入 cout< cout< cout< cout< temp+=x[i]*w[i];//循环求装入背包的物品总重量 } //打印出装入背包的物品的总重量和总价值 cout<<"装入背包的物品的总重量: "< cout<<"装入背包的物品的总价值: "< //释放动态申请的二维数组的内存 for(inti=0;i<=n;i++) delete[]m[i]; delete[]m; printf("Thetimeis%6.3f\n",(double)(end-start-over)/CLK_TCK); return0; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 物联 1301 班刘悦 08080112