1、算法设计与分析实验报告算法分析与设计实验报告专业: 计算机 班级: 计081 姓名: 刘浔 学号: 082551 完成日期: 2011年5月12日 实验一 算法实现一一、 实验目的与要求熟悉C/C+语言的集成开发环境;通过本实验加深对分治法、贪心算法的理解。二、 实验内容:掌握分治法、贪心算法的概念和基本思想,并结合具体的问题学习如何用相应策略进行求解的方法。三、 实验题1. 【伪造硬币问题】给你一个装有n个硬币的袋子。n个硬币中有一个是伪造的。你的任务是找出这个伪造的硬币。为了帮助你完成这一任务,将提供一台可用来比较两组硬币重量的仪器,利用这台仪器,可以知道两组硬币的重量是否相同。试用分治法
2、的思想写出解决问题的算法,并计算其时间复杂度2.【找零钱问题】一个小孩买了价值为33美分的糖,并将1美元的钱交给售货员。售货员希望用数目最少的硬币找给小孩。假设提供了数目有限的面值为25美分、10美分、5美分、及1美分的硬币。给出一种找零钱的贪心算法。四、 实验步骤理解算法思想和问题要求;编程实现题目要求;上机输入和调试自己所编的程序;验证分析实验结果;整理出实验报告。五、 实验程序1、伪造硬币问题#include#include#includeusing namespace std;#define size 1000int asize;/称重函数 m,n分别为数组的最小及最大下标,每次把硬币
3、等分三堆int weight(int m,int n) int i=0,j=0; int sum1=0,sum2=0,sum3=0; if(m=n) return -1; for (i=0;i(n-m+1)/3;i+,j+) sum1 += (am+j); sum2 += (am+(n-m+1)/3+j); sum3 += (am+2*(n-m+1)/3+j); /数组元素个数除三余一的情况if(n-m+1)%3)=1) if(sum1=sum2) if(sum1=sum3) if(an=an-1) return -1; /硬币重量全相等,不符合要求 else return n;/三堆重量相等
4、,剩余一个即为假币 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(n-m+1)%3)=2) if(sum1=sum2) if(sum1=sum3) if(an=an-2) if(an-1=an-2) return -1; /硬币重量全相等,不符合题目要求 else
5、 return n-1;/倒数第二个硬币为假币 else return n;/最后一个为假币 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 /假币在第三堆中
6、 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); void main() int i,n; int t,f,k; int m; cout请输入硬币个数:n; cout请输入真币和伪造硬币的重量tf; for(i=0;isize;i+) /初始化数组 asize=0; for(i=0;in;i+) ai=t; k=rand()%n; /随机产
7、生假硬币的下标 ak=f; /*cout随机产生的伪造硬币的位置endl; coutkendl;*/ cout随机产生的硬币排列顺序endl; for(i=0;in;i+) coutai ; if(i+1)%20=0) coutendl; coutendl; m=weight(0,n-1); if(m=-1) cout恭喜您!没有伪造硬币endl; else cout伪造硬币的位置是endl; coutmendl;2、找零问题#includevoid main() int i,j; int value,repay,money; printf(糖的价值为:); scanf(%d,&value);
8、 printf(小孩给售货员的钱为:); scanf(%d,&money); repay=money-value; printf(售货员应找零:%dn,repay); printf(*n); printf(现有25美分、10美分、5美分和1美分面值的硬币,数目最少的找零办法为:nn); i=repay/25; repay-=i*25; printf(应找25美分个数为:%dn,i); i=repay/10; repay-=i*10; printf(应找10美分个数为:%dn,i); i=repay/5; repay-=i*5; printf(应找5美分个数为:%dn,i); i=repay;
9、printf(应找1美分个数为:%dn,i); printf(*n);六、 实验结果七、 实验分析分治策略:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。贪心算法是指,从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。当达到某算法中的某一步不能再继续前进时,算法停止。在硬币找零问题中其实没有能很好的运用贪心算法来解决问题。实验二 算法实现二一、 实验目的与要求熟悉C/C+语言的集成开
10、发环境;通过本实验加深对贪心算法、动态规划和回溯算法的理解。二、 实验内容:掌握贪心算法、动态规划和回溯算法的概念和基本思想,分析并掌握0-1背包问题的三种算法,并分析其优缺点。三、 实验题1. 0-1背包问题的贪心算法2. 0-1背包问题的动态规划算法3. 0-1背包问题的回溯算法四、 实验步骤理解算法思想和问题要求;编程实现题目要求;上机输入和调试自己所编的程序;验证分析实验结果;整理出实验报告。五、 实验程序1“0-1”背包之贪心算法#include#define N 100void swap(float,float,int,int);void sort(float ,float ,in
11、t);void main () int i,n; float s=0,sum; float wN,vN; int xN; printf(-0-1背包之贪心算法-n); printf(请输入物品的个数:); scanf(%d,&n); printf(请输入背包的总重量:); scanf(%f,&sum); printf(请分别输入物品的重量和价值:n); for(i=0;in;i+) scanf(%f%f,&wi,&vi); xi=0; sort(v,w,n); printf(n物品价值由大到小分别为: ); for(i=0;in;i+) printf(%5.1f,vi); for(i=0;in
12、;i+) if(wi=sum) xi=1; sum-=wi; s+=xi*vi; printf(n贪心算法所选择的物品有(价值): ); for(i=0;in;i+) if(xi=1) printf(%5.1f,vi); printf(n背包内物品的总价值为:%5.2fn,s);void swap(float a,float b,int m,int n) float t1,t2; t1=am; am=an; an=t1; t2=bm; bm=bn; bn=t2;void sort(float a,float b,int n) int i,j; for(i=0;in-1;i+) for(j=0;
13、jn-i;j+) if(ajaj+1) swap(a,b,j,j+1);2“0-1”背包问题之动态规划算法#include#define max(a,b) ab?a:b#define M 100void display(int &n,int &C,int sM,int pM) int i; coutn; coutendl; coutC; coutendl; cout请输入各物体的大小或重量:endl; s0=0; for(i=1;isi; cout请输入各物体的价值p:endl; p0=0; for(i=1;ipi;int knapsack(int &n,int &C,int sM,int p
14、M,int VMM) int i,j; for (i=0;i=n;i+) for(j=0;jj) Vij=Vi-1j; else if(si=j) Vij=max(Vi-1j,Vi-1j-si+pi); return VnC; void traceback(int n,int C,int sM,int xM,int VMM) for(int i=1;i0)?1:0;void main() int i,j,n,C; char ch; int sM,pM,xM; int VMM; while(1) display(n,C,s,p); cout运算结果如下:endl; for(i=1;i=n;i+)
15、 xi=0; knapsack(n,C,s,p,V); cout ; for(j=0;j=C;j+) coutj ; coutendl; for(i=0;i=n;i+) couti ; for(j=0;j=C;j+) coutVij ; coutendl; coutendl; cout选择的物体向量表示为:; cout ( ; traceback(n,C,s,x,V); for(i=1;i=n;i+) coutxi ; cout)endl; cout背包最大价值为:VnCendl; coutendl; cout按Y或y继续操作,否则按任意键ch; if(ch=Y|ch=y) continue;
16、 else break; 3“0-1”背包问题之回溯算法#include #include#includeint min(int w,int c)int temp; if (wc) temp=w; else temp=c; return temp;void knapsack(int v,int w,int c,int n,int*m) /求最优值 int jmax=min(wn-1,c); for(int j=0;j=jmax;j+) mnj=0; for(int jj=wn;jj1;i-) /递归部分 jmax=min(wi-1,c); for(int j=0;j=jmax;j+) mij=
17、mi+1j; for(int jj=wi;jj=w1) m1c=max(m1c,m2c-w1+v1); cout最优值:m1cendl; for(int l=2;l=n;l+) for(int j=0;j=c;j+) coutmljsetw(c-1); coutendl; cout*endl;int traceback(int *m,int w,int c,int n,int x) /回代,求最优解 cout得到的一组最优解如下:endl; for(int i=1;in;i+) if(mic=mi+1c) xi=0; else xi=1; c-=wi; xn=(mnc)?1:0; for(in
18、t y=1;y=n;y+) coutsetw(5)xy; return xn;main() int n,c; int *m; cout-0-1背包问题之回溯-endl; coutnc; int *v=new intn+1; cout输入各物品价值 (vi):endl; for(int i=1;ivi; int *w=new intn+1; cout输入各物品重量 (wi):endl; for(int j=1;jwj; int *x=new intn+1; m=new int*n+1; /动态的分配二维数组 for(int p=0;pn+1;p+) mp=new intc+1; knapsack
19、(v,w,c,n,m); traceback(m,w,c,n,x);六、 实验结果七、 实验分析本实验通过贪心算法、动态规划和回溯算法三种算法求解0-1背包问题,从而了解三种算法优缺点。贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。动态规划的实质是分治思想和解决冗余,因此,动态规划是一种将问题实例分解为更小的、相似的子问题,并存储子问题的解而避免计算重复的子问题,以解决最优化问题的算法策略。回溯算法是一种系统地搜索问题的解的方法。回溯算法的基本思想是:深度搜索,一支一支进行搜索,直到找到最优可行解或搜索结束。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1