算法分析与设计实验报告Word格式.docx
《算法分析与设计实验报告Word格式.docx》由会员分享,可在线阅读,更多相关《算法分析与设计实验报告Word格式.docx(27页珍藏版)》请在冰豆网上搜索。
for(i=1;
i<
=n;
i++)
q[i]=2;
}
k=rand()%n;
if(k==0)
k=n;
q[k]=1;
cout<
"
随机产生的硬币排列顺序"
endl;
for(i=1;
cout<
q[i]<
;
if(i%5==0)
cout<
}
intp=findTheCoin(q,1,n);
伪造硬币的位置:
p<
======================="
}
intquantity(intq[],inta,intb)
inttotal=0;
for(i=a;
=b;
total+=q[i];
returntotal;
intfindTheCoin(intq[],inta,intb)
if(a==b)
returna;
intn=b-a+1;
intc=n%3;
intm=a+n/3-1;
intd;
switch(c)
case0:
if(quantity(q,a,m)==quantity(q,m+1,m+n/3))
{
d=findTheCoin(q,m+n/3+1,m+2*(n/3));
returnd;
}
elseif(quantity(q,a,m)==quantity(q,m+n/3+1,m+2*(n/3)))
d=findTheCoin(q,m+1,m+n/3);
else
d=findTheCoin(q,a,m);
//break;
case1:
if((quantity(q,a,m)==quantity(q,m+1,m+n/3))&
&
(quantity(q,m+n/3+1,m+2*(n/3))==quantity(q,m+1,m+n/3)))
returnm+2*(n/3)+1;
if(quantity(q,a,m)==quantity(q,m+1,m+n/3))
{
d=findTheCoin(q,m+n/3+1,m+2*(n/3));
returnd;
}
elseif(quantity(q,a,m)==quantity(q,m+n/3+1,m+2*(n/3)))
d=findTheCoin(q,m+1,m+n/3);
else
d=findTheCoin(q,a,m);
case2:
if(q[m+2*(n/3)+1]==q[m+2*(n/3)+2])
else
else
{
if(q[m+2*(n/3)+2]==q[1])
returnm+2*(n/3)+1;
//cout<
伪造硬币的号码是"
3*m+1<
returnm+2*(n/3)+2;
3*m+2<
//returntrue;
(2)运行结果
2.【找零钱问题】一个小孩买了价值为33美分的糖,并将1美元的钱交给售货员。
售货员希望用数目最少的硬币找给小孩。
假设提供了数目有限的面值为25美分、10美分、5美分、及1美分的硬币。
给出一种找零钱的贪心算法。
(1)源程序:
stdio.h>
intmakeChange(intmoney,intcoin25,intcoin10,intcoin5,intcoin1)
inti=0,j=0;
while(money)
if(money>
=25)
i=money/25;
if(i<
=coin25)
money=money-25*i;
j+=i;
cout<
需要25美分"
个!
money=money-25*coin25;
j+=coin25;
coin25<
if(money>
=10)
i=money/10;
=coin10)
money=money-10*i;
需要10美分"
money=money-10*coin10;
j+=coin10;
coin10<
=5)
i=money/5;
=coin5)
money=money-5*i;
需要5美分"
money=money-5*coin5;
j+=coin5;
coin5<
=1)
i=money/1;
=coin1)
money=money-1*i;
需要1美分"
!
零钱不够,无法找零!
!
请退出后重新操作!
return0;
共需要"
j<
个硬币!
return1;
intmoney,smoney,ymoney;
intcoin25,coin10,coin5,coin1;
欢迎使用,按0可退出!
请输入各面值硬币的个数:
25美分个数:
cin>
coin25;
10美分个数:
coin10;
5美分个数:
coin5;
1美分个数:
coin1;
应收:
cin>
ymoney;
if(ymoney==0)
break;
实收:
smoney;
money=smoney-ymoney;
您要找"
money<
美分!
if(money==0)
continue;
makeChange(money,coin25,coin10,coin5,coin1);
==========================="
四、实验步骤
理解算法思想和问题要求;
编程实现题目要求;
上机输入和调试自己所编的程序;
验证分析实验结果;
整理出实验报告。
五、实验感想
找零钱问题生活中也很常见,问题也很简单,所以变成没有费很大力气。
伪造硬币问题因为涉及到函数的递归调用,所以在编程时在递归调用函数时结果的返回出了许多错误,先检查了自己的算法,弄清思路是没有问题的,可能在写程序时犯了一些逻辑错误,后来经过一组测试数据,自己在纸上模拟程序单步执行,终于找到了自己犯得错误,问题迎刃而解。
实验二算法实现二
通过本实验加深对贪心算法、动态规划和回溯算法的理解。
掌握贪心算法、动态规划和回溯算法的概念和基本思想,分析并掌握"
0-1"
背包问题的三种算法,并分析其优缺点。
1."
背包问题的贪心算法
(1)源程序
#definemax100
voidsort(intn,floata[max],floatb[max])
{
intj,h,k;
floatt1,t2,t3,c[max];
for(k=1;
k<
k++)
c[k]=a[k]/b[k];
for(h=1;
h<
n;
h++)
for(j=1;
=n-h;
j++)
if(c[j]<
c[j+1])
t1=a[j];
a[j]=a[j+1];
a[j+1]=t1;
t2=b[j];
b[j]=b[j+1];
b[j+1]=t2;
t3=c[j];
c[j]=c[j+1];
c[j+1]=t3;
}
}
voidknapsack(intn,floatlimitw,floatv[max],floatw[max],intx[max])
floatc1;
sort(n,v,w);
货物按价值密度排序后为:
价值:
v[i]<
endl<
重量:
w[i]<
c1=limitw;
i++)
{
if(w[i]>
c1)
x[i]=1;
c1=c1-w[i];
voidmain()
intn,i,x[max];
floatv[max],w[max],totalv=0,totalw=0,limitw;
请输入货物数量:
背包最大载重:
limitw;
for(i=1;
x[i]=0;
请依次输入物品的价值:
cin>
v[i];
请依次输入物品的重量:
w[i];
knapsack(n,limitw,v,w,x);
装载结果为:
x[i]<
if(x[i]==1)
totalw=totalw+w[i];
totalv=totalv+v[i];
}
背包的总重量为:
totalw<
背包的总价值为:
totalv<
============================="
2."
背包问题的动态规划算法
intc[10][100];
intknapsack(intwmax,intn)
inti,j,w[10],p[10];
请输入每个物品的重量:
请输入每个物品的价值:
p[i];
for(i=0;
10;
for(j=0;
100;
j++)
c[i][j]=0;
=wmax;
if(w[i]<
=j)
if(p[i]+c[i-1][j-w[i]]>
c[i-1][j])
c[i][j]=p[i]+c[i-1][j-w[i]];
else
c[i][j]=c[i-1][j];
c[i][j]=c[i-1][j];
return(c[n][wmax]);
intmain()
intwmax,n,i,j;
请输入背包的载重:
wmax;
请输入货物数量:
装载的最大价值为:
knapsack(wmax,n)<
return0;
3."
背包问题的回溯算法
iostream>
usingnamespacestd;
classKnap
friendintKnapsack(intp[],intw[],intc,intn);
public:
voidprint()
for(intm=1;
m<
m++)
bestx[m]<
};
private:
intBound(inti);
voidBacktrack(inti);
intc;
//背包容量
intn;
//物品数
int*w;
//物品重量数组
int*p;
//物品价值数组
intcw;
//当前重量
intcp;
//当前价值
intbestp;
//当前最优值
int*bestx;
//当前最优解
int*x;
//当前解
};
intKnap:
:
Bound(inti)
{//计算上界
intcleft=c-cw;
//剩余容量
intb=cp;
//以物品单位重量价值递减序装入物品
while(i<
=n&
=cleft)
cleft-=w[i];
b+=p[i];
i++;
}//装满背包
if(i<
=n)
b+=p[i]/w[i]*cleft;
returnb;
voidKnap:
Backtrack(inti)
if(i>
n)
if(bestp<
cp)
for(intj=1;
bestx[j]=x[j];
bestp=cp;
return;
if(cw+w[i]<
=c)//搜索左子树
cw+=w[i];
cp+=p[i];
Backtrack(i+1);
cw-=w[i];
cp-=p[i];
if(Bound(i+1)>
bestp)//搜索右子树
x[i]=0;
classObject
friendintKnapsack(intp[],intw[],intc,intn);
intoperator<
=(Objecta)const
return(d>
=a.d);
intID;
floatd;
intKnapsack(intp[],intw[],intc,intn)
{//为Knap:
Backtrack初始化
intW=0;
intP=0;
inti=1;
Object*Q=newObject[n];
Q[i-1].ID=i;
Q[i-1].d=1.0*p[i]/w[i];
P+=p[i];
W+=w[i];
if(W<
=c)
returnP;
//装入所有物品
//依物品单位重量排序
floatf;
for(i=0;
for(intj=i;
if(Q[i].d<
Q[j].d)
{
f=Q[i].d;
Q[i].d=Q[j].d;
Q[j].d=f;
KnapK;
K.p=newint[n+1];
K.w=newint[n+1];
K.x=newint[n+1];
K.bestx=newint[n+1];
K.x[0]=0;
K.bestx[0]=0;
for(i=1;
K.p[i]=p[Q[i-1].ID];
K.w[i]=w[Q[i-1].ID];
K.cp=0;
K.cw=0;
K.c=c;
K.n=n;
K.bestp=0;
//回溯搜索
K.Backtrack
(1);
K.print();
delete[]Q;
delete[]K.w;
delete[]K.p;
returnK.bestp;
intc=0;
intn=0;
inti=0;
//chark;
while(true)
请输入背包容量:
c;
请输入物品的个数:
p=newint[n+1];
w=newint[n+1];
p[0]=0;
w[0]=0;
请输入物品的价值:
请输入物品的重量:
最优解为:
//cout<
最优值为(bestp):
Knapsack(p,w,c,n)<
=========================="
[s]重新开始"
[q]退出"
//cin>
k;
五、实验感想
贪心算法只考虑眼前的利益而不考虑长远利益,得到的可能不是最优解,所以编程时一步