01背包动态规划回溯和背包贪心实验报告.docx
- 文档编号:26716632
- 上传时间:2023-06-22
- 格式:DOCX
- 页数:18
- 大小:242.77KB
01背包动态规划回溯和背包贪心实验报告.docx
《01背包动态规划回溯和背包贪心实验报告.docx》由会员分享,可在线阅读,更多相关《01背包动态规划回溯和背包贪心实验报告.docx(18页珍藏版)》请在冰豆网上搜索。
01背包动态规划回溯和背包贪心实验报告
西安郵電學院
算法设计与分析课内试验报告
题目:
0-1背包(动态规划、回溯)和背包(贪心)
院系名称:
计算机学院
专业名称:
软件工程专业
班级:
0903班
学生姓名:
张桥
学号(8位):
04095091(23)
指导教师:
陈琳
时间:
2011年12月
一.设计目的
通过上机实验:
深刻理解和掌握0-1背包(动态规划算法、回溯算法)和背包(贪心算法)的问题描述、算法设计思想、程序设计、算法复杂性分析、他们的区别及联系。
二.设计内容
1问题的描述
(1)0-1背包问题
给定n种物品和一背包。
物品i的重量是wi,其价值为vi,背包的容量为c。
问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大
(2)背包问题与0-1背包问题类似,所不同的是在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部装入背包,1<=i<=n。
2算法设计思想
(1)0-1背包问题
动态规划法:
是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。
在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。
依次解决各子问题,最后一个子问题就是初始问题的解。
由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中。
设所给0-1背包问题的子问题的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。
由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下。
回溯法:
在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。
算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。
如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。
(2)背包问题
贪心算法:
首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。
若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。
依此策略一直地进行下去,直到背包装满为止。
三.测试数据及运行结果
1.正常测试数据(3组)及运行结果
0-1背包问题:
动态规划法:
回溯法:
背包问题:
贪心算法:
四.调试情况,设计技巧及体会
本次的实验大体理解和掌握0-1背包(动态规划算法、回溯算法)和背包(贪心算法)的问题描述、算法设计思想、程序设计、算法复杂性分析、他们的区别及联系。
通过本次上机实验,我对0-1背包(动态规划算法、回溯算法)和背包(贪心算法)有了更为深刻的了解,利用动态规划算法、回溯算法和贪心可以将问题简化,这有助于我们在实际问题中解决一些复杂性较大的问题,提高程序的运行效率。
但要注意他们的区别与不同的应用场景。
五.源代码
1)0-1背包:
动态规划法:
#include<>
#defineMAX20
voidKnapsack(int*value,int*weight,intcolumn,intlength,int(*middle)[MAX]);
voidTraceBack(int(*middle)[MAX],int*weight,intcolumn,intlength,int*x);
intMax(intx,inty);
intMin(intx,inty);
intMin(intx,inty)
{
returnx<=yx:
y;
}
intMax(intx,inty)
{
returnx>=yx:
y;
}
voidTraceBack(int(*middle)[MAX],int*weight,intcolumn,intlength,int*x)
{
inti;
for(i=1;i if(middle[i][column]==middle[i+1][column]) x[i]=0; else { x[i]=1; column-=weight[i]; } x[length]=(middle[length][column]1: 0); } voidKnapsack(int*value,int*weight,intcolumn,intlength,int(*middle)[MAX]) { inti,j,jMax=Min(weight[length]-1,column); for(j=0;j<=jMax;j++) middle[length][j]=0; for(j=weight[length];j<=column;j++) middle[length][j]=value[length]; for(i=length-1;i>1;i--) { jMax=Min(weight[i]-1,column); for(j=0;j<=jMax;j++) middle[i][j]=middle[i+1][j]; for(j=weight[i];j<=column;j++) middle[i][j]=Max(middle[i+1][j],middle[i+1][j-weight[i]]+value[i]); } middle[1][column]=middle[2][column]; if(column>=weight[1]) middle[1][column]=Max(middle[1][column],middle[2][column-weight[1]]+value[1]); } voidmain(void) { inti,length,column,count=0,weight[MAX],value[MAX],x[MAX]={0},middle[MAX][MAX]={0}; printf("请输入背包总容量: \n"); scanf("%d",&column); printf("请输入物品个数: \n"); scanf("%d",&length); if(length<1) { printf("输入错误! ! ! \n"); return; } for(i=1;i<=length;i++) { printf("请输入第%d个物品的重量及价值: \n",i); scanf("%d%d",weight+i,value+i); } Knapsack(value,weight,column,length,middle); TraceBack(middle,weight,column,length,x); printf("Result: \n"); for(i=1;i<=length;i++) if(x[i]) printf("Number: %d,",i); printf("\n"); } 回溯法: #include<> #include<> #include<> typedefstructgoods { intnum; double*value; double*weight; int*location; doublecolumn; doublecurrentWeight; doublecurrentValue; doublebestValue; }GOODS; voidKnapsack(GOODS*goods,inti); doubleBound(GOODS*goods,inti); voidSwapDouble(double*m,double*n); voidSwapInt(int*m,int*n); voidSort(GOODS*goods); voidSort(GOODS*goods) { inti,j; double*temp; temp=(double*)malloc(sizeof(goods->num+1)); for(i=1;i<=goods->num;i++) temp[i]=goods->value[i]/goods->weight[i]; for(i=1;i { for(j=i+1;j<=goods->num;j++) { if(temp[i] { SwapDouble(&temp[i],&temp[j]); SwapDouble(&goods->weight[i],&goods->weight[j]); SwapDouble(&goods->value[i],&goods->value[j]); SwapInt(&goods->location[i],&goods->location[j]); } } } } voidSwapInt(int*m,int*n) { inttemp; temp=*m; *m=*n; *n=temp; } voidSwapDouble(double*m,double*n) { doubletemp; temp=*m; *m=*n; *n=temp; } doubleBound(GOODS*goods,inti) { doubleleftWeight=goods->column-goods->currentWeight; doublebound=goods->currentValue; while(i<=goods->num&&goods->weight[i]<=leftWeight) { leftWeight-=goods->weight[i]; bound+=goods->value[i]; i++; } if(i<=goods->num) bound+=goods->value[i]*leftWeight/goods->weight[i]; returnbound; } voidKnapsack(GOODS*goods,inti) { if(i>goods->num) { goods->bestValue=goods->currentValue; return; } if(goods->currentWeight+goods->weight[i]<=goods->column) { goods->location[i]=1; goods->currentWeight+=goods->weight[i]; goods->currentValue+=goods->value[i]; Knapsack(goods,i+1); goods->currentWeight-=goods->weight[i]; goods->currentValue-=goods->value[i]; } if(Bound(goods,i+1)>goods->bestValue) { goods->location[i]=0; Knapsack(goods,i+1); } } voidmain(void) { inti; doubletotalValue,totalWeight,sumWeight; GOODS*goods=NULL; totalValue=totalWeight=sumWeight=; if(! (goods=(GOODS*)malloc(sizeof(GOODS)))) { printf("内存分配失败\n"); exit(0); } goods->currentValue=goods->currentWeight=goods->bestValue=; printf("请输入背包最大重量: \n"); scanf("%lf",&goods->column); printf("请输入可选物品数量: \n"); scanf("%d",&goods->num); if(! (goods->value=(double*)malloc(sizeof(double)*(goods->num+1)))) { printf("内存分配失败\n"); exit(0); } if(! (goods->weight=(double*)malloc(sizeof(double)*(goods->num+1)))) { printf("内存分配失败\n"); exit(0); } if(! (goods->location=(int*)malloc(sizeof(int)*(goods->num+1)))) { printf("内存分配失败\n"); exit(0); } for(i=1;i<=goods->num;i++) goods->location[i]=0; for(i=1;i<=goods->num;i++) { printf("输入第%d号物品的重量和价值: \n",i); scanf("%lf%lf",&goods->weight[i],&goods->value[i]); totalValue+=goods->value[i]; totalWeight+=goods->weight[i]; } Sort(goods); printf("\n排序后的物品内容如下: \n"); printf("\n背包最大能装的重量为: %.2lf\n\n",goods->column); for(i=1;i<=goods->num;i++) printf("第%d号物品重: %.2lf,价值: %.2lf\n",i,goods->weight[i],goods->value[i]); printf("\n所有物品总重量为: %.2lf,总价值为: %.2lf\n\n",totalWeight,totalValue); Knapsack(goods,1); printf("\n可将以下物品装入背包,使背包装的物品价值最大: \n"); for(i=1;i<=goods->num;i++) if(goods->location[i]) { printf("第%d号物品,重量: %.2lf,价值: %.2lf\n",i,goods->weight[i],goods->value[i]); sumWeight+=goods->weight[i]; } printf("\n背包中物品最大重量为: %.2lf,最大价值为: %.2lf\n",sumWeight,goods->bestValue); } 2)背包问题: 贪心算法: #include<> #defineMAX10 voidKnapsack(int*value,int*weight,intcolumn,intlength,double(*middle)[MAX]); voidSort(double(*middle)[MAX],intlength); voidSwap(double*m,double*n); voidSwap(double*m,double*n) { doubletemp; temp=*m; *m=*n; *n=temp; } voidSort(double(*middle)[MAX],intlength) { inti,j; for(i=0;i { for(j=i+1;j { if(middle[1][i] { Swap(&middle[0][j],&middle[0][i]); Swap(&middle[1][j],&middle[1][i]); } } } } voidKnapsack(int*value,int*weight,intcolumn,intlength,double(*middle)[MAX]) { inti,leftColumn=column,temp; for(i=0;i { middle[0][i]=i+1; middle[1][i]=value[i]*/weight[i]; } Sort(middle,length); for(i=0;leftColumn>0&&i { temp=weight[(int)middle[0][i]-1]; if(temp<=leftColumn) { leftColumn-=temp; middle[2][i]=temp; } else { middle[2][i]=leftColumn; break; } } } voidmain(void) { inti,length,column,count=0,weight[MAX],value[MAX]; doublemiddle[MAX][MAX]={0},sum=; printf("请输入背包总容量: \n"); scanf("%d",&column); printf("请输入物品个数: \n"); scanf("%d",&length); if(length<1) { printf("输入错误! ! ! \n"); return; } for(i=0;i { printf("请输入第%d个物品的重量及价值: \n",i+1); scanf("%d%d",weight+i,value+i); } Knapsack(value,weight,column,length,middle); printf("Result: \n"); for(i=0;i if(middle[2][i]) { printf("Number: %d,Weight: %.2lf\n",(int)middle[0][i],middle[2][i]); sum+=middle[2][i]*middle[1][i]; } printf("SumValue: %.2lf",sum); printf("\n"); }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 01 背包 动态 规划 回溯 贪心 实验 报告