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;iif(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;inum;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;iif(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");
}