算法设计与分析实验报告.docx

上传人:b****7 文档编号:9638096 上传时间:2023-02-05 格式:DOCX 页数:21 大小:131.88KB
下载 相关 举报
算法设计与分析实验报告.docx_第1页
第1页 / 共21页
算法设计与分析实验报告.docx_第2页
第2页 / 共21页
算法设计与分析实验报告.docx_第3页
第3页 / 共21页
算法设计与分析实验报告.docx_第4页
第4页 / 共21页
算法设计与分析实验报告.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

算法设计与分析实验报告.docx

《算法设计与分析实验报告.docx》由会员分享,可在线阅读,更多相关《算法设计与分析实验报告.docx(21页珍藏版)》请在冰豆网上搜索。

算法设计与分析实验报告.docx

算法设计与分析实验报告

《算法分析与设计》

实验报告

 

专业:

计算机

班级:

计081

姓名:

刘浔

学号:

082551

完成日期:

2011年5月12日

 

实验一算法实现一

一、实验目的与要求

熟悉C/C++语言的集成开发环境;

通过本实验加深对分治法、贪心算法的理解。

二、实验内容:

掌握分治法、贪心算法的概念和基本思想,并结合具体的问题学习如何用相应策略进行求解的方法。

三、实验题

1.【伪造硬币问题】给你一个装有n个硬币的袋子。

n个硬币中有一个是伪造的。

你的任务是找出这个伪造的硬币。

为了帮助你完成这一任务,将提供一台可用来比较两组硬币重量的仪器,利用这台仪器,可以知道两组硬币的重量是否相同。

试用分治法的思想写出解决问题的算法,并计算其时间复杂度

2.【找零钱问题】一个小孩买了价值为33美分的糖,并将1美元的钱交给售货员。

售货员希望用数目最少的硬币找给小孩。

假设提供了数目有限的面值为25美分、10美分、5美分、及1美分的硬币。

给出一种找零钱的贪心算法。

四、实验步骤

理解算法思想和问题要求;

编程实现题目要求;

上机输入和调试自己所编的程序;

验证分析实验结果;

整理出实验报告。

五、实验程序

1、伪造硬币问题

#include

#include

#include

usingnamespacestd;

#definesize1000

inta[size];

//称重函数m,n分别为数组的最小及最大下标,每次把硬币等分三堆

intweight(intm,intn){

inti=0,j=0;

intsum1=0,sum2=0,sum3=0;

if(m>=n)

return-1;

for(i=0;i<(n-m+1)/3;i++,j++)

{

sum1+=(a[m+j]);

sum2+=(a[m+(n-m+1)/3+j]);

sum3+=(a[m+2*(n-m+1)/3+j]);

}

//数组元素个数除三余一的情况

if(((n-m+1)%3)==1)

{

if(sum1==sum2)

{

if(sum1==sum3)

{if(a[n]==a[n-1])

return-1;//硬币重量全相等,不符合要求

else

returnn;//三堆重量相等,剩余一个即为假币

}

else//假币在第三堆中

{m=m+2*((n-m+1)/3);

weight(m,n);

}

}

elseif(sum1==sum3)//假币在第二堆中

{m=m+(n-m+1)/3;

n=m+2*((n-m+1)/3)-1;

weight(m,n);

}

else//假币在第一堆中

{

n=m+(n-m+1)/3-1;

weight(m,n);

}

}

//数组元素个数除三余二的情况

elseif(((n-m+1)%3)==2)

{if(sum1==sum2)

{

if(sum1==sum3)

{if(a[n]==a[n-2])

{

if(a[n-1]==a[n-2])

return-1;//硬币重量全相等,不符合题目要求

else

returnn-1;//倒数第二个硬币为假币

}

else

returnn;//最后一个为假币

}

else//假币在第三堆中

{

m=m+2*((n-m+1)/3);

weight(m,n);

}

}

else

if(sum1==sum3)//假币在第二堆中

{m=m+(n-m+1)/3;

n=m+2*((n-m+1)/3)-1;

weight(m,n);

}

else//假币在第一堆中

{

n=m+(n-m+1)/3-1;

weight(m,n);

}

}

//数组元素个数被三整除的情况

else

if(sum1==sum2)

{if(sum1==sum3)

return-1;//三堆全相等,不符合题目要求

else//假币在第三堆中

{

m=m+2*((n-m+1)/3);

weight(m,n);

}

}

else

{if(sum1==sum3)

{//假币在第二堆中

m=m+(n-m+1)/3;

n=m+2*((n-m+1)/3)-1;

weight(m,n);

}

else

{//假币在第一堆中

n=m+(n-m+1)/3-1;

weight(m,n);

}

}

}

voidmain()

{inti,n;

intt,f,k;

intm;

cout<<"请输入硬币个数:

"<

cin>>n;

cout<<"请输入真币和伪造硬币的重量"<

cin>>t>>f;

for(i=0;i

a[size]=0;

for(i=0;i

a[i]=t;

k=rand()%n;//随机产生假硬币的下标

a[k]=f;

/*cout<<"随机产生的伪造硬币的位置"<

cout<

cout<<"随机产生的硬币排列顺序"<

for(i=0;i

{

cout<

if((i+1)%20==0)

cout<

}

cout<

m=weight(0,n-1);

if(m==-1)

cout<<"恭喜您!

没有伪造硬币"<

else

cout<<"伪造硬币的位置是"<

cout<

}

2、找零问题

#include

voidmain()

{inti,j;

intvalue,repay,money;

printf("糖的价值为:

");

scanf("%d",&value);

printf("小孩给售货员的钱为:

");

scanf("%d",&money);

repay=money-value;

printf("售货员应找零:

%d\n",repay);

printf("***********************************\n");

printf("现有25美分、10美分、5美分和1美分面值的硬币,数目最少的找零办法为:

\n\n");

i=repay/25;

repay-=i*25;

printf("应找25美分个数为:

%d\n",i);

i=repay/10;

repay-=i*10;

printf("应找10美分个数为:

%d\n",i);

i=repay/5;

repay-=i*5;

printf("应找5美分个数为:

%d\n",i);

i=repay;

printf("应找1美分个数为:

%d\n",i);

printf("***********************************\n");

}

六、实验结果

七、实验分析

分治策略:

对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。

这种算法设计策略叫做分治法。

贪心算法是指,从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。

当达到某算法中的某一步不能再继续前进时,算法停止。

在硬币找零问题中其实没有能很好的运用贪心算法来解决问题。

实验二算法实现二

一、实验目的与要求

熟悉C/C++语言的集成开发环境;

通过本实验加深对贪心算法、动态规划和回溯算法的理解。

二、实验内容:

掌握贪心算法、动态规划和回溯算法的概念和基本思想,分析并掌握"0-1"背包问题的三种算法,并分析其优缺点。

三、实验题

1."0-1"背包问题的贪心算法

2."0-1"背包问题的动态规划算法

3."0-1"背包问题的回溯算法

四、实验步骤

理解算法思想和问题要求;

编程实现题目要求;

上机输入和调试自己所编的程序;

验证分析实验结果;

整理出实验报告。

五、实验程序

1.“0-1”背包之贪心算法

#include

#defineN100

voidswap(float,float,int,int);

voidsort(float[],float[],int);

voidmain()

{

inti,n;

floats=0,sum;

floatw[N],v[N];

intx[N];

printf("------------0-1背包之贪心算法-------------\n");

printf("请输入物品的个数:

");

scanf("%d",&n);

printf("请输入背包的总重量:

");

scanf("%f",&sum);

printf("请分别输入物品的重量和价值:

\n");

for(i=0;i

{scanf("%f%f",&w[i],&v[i]);

x[i]=0;

}

sort(v,w,n);

printf("\n物品价值由大到小分别为:

");

for(i=0;i

for(i=0;i

{if(w[i]<=sum)

{x[i]=1;

sum-=w[i];

}

s+=x[i]*v[i];

}

printf("\n贪心算法所选择的物品有(价值):

");

for(i=0;i

if(x[i]==1)

printf("%5.1f",v[i]);

printf("\n背包内物品的总价值为:

%5.2f\n",s);

}

voidswap(floata[],floatb[],intm,intn)

{floatt1,t2;

t1=a[m];

a[m]=a[n];

a[n]=t1;

t2=b[m];

b[m]=b[n];

b[n]=t2;

}

voidsort(floata[],floatb[],intn)

{inti,j;

for(i=0;i

for(j=0;j

if(a[j]

{swap(a,b,j,j+1);}

}

2.“0-1”背包问题之动态规划算法

#include

#definemax(a,b)a>b?

a:

b

#defineM100

voiddisplay(int&n,int&C,ints[M],intp[M])

{

inti;

cout<<"请输入物体数n:

";

cin>>n;

cout<

cout<<"请输入背包总容量C:

";

cin>>C;

cout<

cout<<"请输入各物体的大小或重量:

"<

s[0]=0;

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

cin>>s[i];

cout<<"请输入各物体的价值p:

"<

p[0]=0;

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

cin>>p[i];

};

intknapsack(int&n,int&C,ints[M],intp[M],intV[M][M])

{

inti,j;

for(i=0;i<=n;i++)

for(j=0;j<=C;j++)

{

if(i==0||j==0)

V[i][j]=0;

elseif(s[i]>j)

V[i][j]=V[i-1][j];

elseif(s[i]<=j)

V[i][j]=max(V[i-1][j],V[i-1][j-s[i]]+p

[i]);

}

returnV[n][C];

};

voidtraceback(intn,intC,ints[M],intx[M],intV[M][M])

{

for(inti=1;i<=n;i++)

{

if(V[i][C]==V[i-1][C])

x[i]=0;

else

{

x[i]=1;

C=C-s[i];

}

}

//x[n]=(V[n][C]>0)?

1:

0;

};

voidmain()

{

inti,j,n,C;

charch;

ints[M],p[M],x[M];

intV[M][M];

while

(1)

{

display(n,C,s,p);

cout<<"运算结果如下:

"<

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

x[i]=0;

knapsack(n,C,s,p,V);

cout<<"";

for(j=0;j<=C;j++)

cout<

cout<

for(i=0;i<=n;i++)

{

cout<

for(j=0;j<=C;j++)

{

cout<

}

cout<

cout<

}

cout<<"选择的物体向量表示为:

";

cout<<"(";

traceback(n,C,s,x,V);

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

cout<

cout<<")"<

cout<<"背包最大价值为:

"<

cout<

cout<<"按Y或y继续操作,否则按任意键"<

cin>>ch;

if(ch=='Y'||ch=='y')

continue;

else

break;

}

}

3.“0-1”背包问题之回溯算法

#include

#include

#include

intmin(intw,intc)

{inttemp;

if(w

else

temp=c;

returntemp;

}

intmax(intw,intc)

{

inttemp;

if(w>c)temp=w;

else

temp=c;

returntemp;

}

voidknapsack(intv[],intw[],intc,intn,int**m)//求最优值

{

intjmax=min(w[n]-1,c);

for(intj=0;j<=jmax;j++)

m[n][j]=0;

for(intjj=w[n];jj<=c;jj++)

m[n][jj]=v[n];

for(inti=n-1;i>1;i--){//递归部分

jmax=min(w[i]-1,c);

for(intj=0;j<=jmax;j++)

m[i][j]=m[i+1][j];

for(intjj=w[i];jj<=c;jj++)

m[i][jj]=max(m[i+1][jj],m[i+1][jj-w[i]]+v[i]);

}

m[1][c]=m[2][c];

if(c>=w[1])

m[1][c]=max(m[1][c],m[2][c-w[1]]+v[1]);

cout<<"最优值:

"<

for(intl=2;l<=n;l++)

for(intj=0;j<=c;j++)

{

cout<

}

cout<

cout<<"*******************************************"<

}

inttraceback(int**m,intw[],intc,intn,intx[])//回代,求最优解

{

cout<<"得到的一组最优解如下:

"<

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;

for(inty=1;y<=n;y++)

{

cout<

}

returnx[n];

}

main()

{

intn,c;

int**m;

cout<<"------------------0-1背包问题之回溯--------------------"<

cout<<"请输入物品个数和重量上限:

";

cin>>n>>c;

int*v=newint[n+1];

cout<<"输入各物品价值(v[i]):

"<

for(inti=1;i<=n;i++)

cin>>v[i];

int*w=newint[n+1];

cout<<"输入各物品重量(w[i]):

"<

for(intj=1;j<=n;j++)

cin>>w[j];

int*x=newint[n+1];

m=newint*[n+1];//动态的分配二维数组

for(intp=0;p

{

m[p]=newint[c+1];

}

knapsack(v,w,c,n,m);

traceback(m,w,c,n,x);

}

六、实验结果

七、实验分析

本实验通过贪心算法、动态规划和回溯算法三种算法求解0-1背包问题,从而了解三种算法优缺点。

贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。

也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。

动态规划的实质是分治思想和解决冗余,因此,动态规划是一种将问题实例分解为更小的、相似的子问题,并存储子问题的解而避免计算重复的子问题,以解决最优化问题的算法策略。

回溯算法是一种系统地搜索问题的解的方法。

回溯算法的基本思想是:

深度搜索,一支一支进行搜索,直到找到最优可行解或搜索结束。

 

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

当前位置:首页 > 党团工作 > 入党转正申请

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

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