贪心算法-找零问题 实验报告
贪心算法 实验报告
贪心算法实验报告贪心算法实验报告引言:贪心算法是一种常用的算法设计策略,它通常用于求解最优化问题。
贪心算法的核心思想是在每一步选择中都选择当前最优的解,从而希望最终能够得到全局最优解。
本实验旨在通过实际案例的研究,探索贪心算法的应用和效果。
一、贪心算法的基本原理贪心算法的基本原理是每一步都选择当前最优解,而不考虑整体的最优解。
这种贪婪的选择策略通常是基于局部最优性的假设,即当前的选择对于后续步骤的选择没有影响。
贪心算法的优点是简单高效,但也存在一定的局限性。
二、实验案例:零钱兑换问题在本实验中,我们以零钱兑换问题为例,来说明贪心算法的应用。
问题描述:假设有不同面值的硬币,如1元、5元、10元、50元和100元,现在需要支付给客户x元,如何用最少的硬币数完成支付?解决思路:贪心算法可以通过每次选择当前面值最大的硬币来求解。
具体步骤如下:1. 初始化一个空的硬币集合,用于存放选出的硬币。
2. 从面值最大的硬币开始,如果当前硬币的面值小于等于待支付金额,则将该硬币放入集合中,并将待支付金额减去该硬币的面值。
3. 重复步骤2,直到待支付金额为0。
实验过程:以支付金额为36元为例,我们可以通过贪心算法求解最少硬币数。
首先,面值最大的硬币为100元,但36元不足以支付100元硬币,因此我们选择50元硬币。
此时,剩余待支付金额为36-50=-14元。
接下来,面值最大的硬币为50元,但待支付金额为负数,因此我们选择下一个面值最大的硬币,即10元硬币。
此时,剩余待支付金额为-14-10=-24元。
继续选择10元硬币,剩余待支付金额为-24-10=-34元。
再次选择10元硬币,剩余待支付金额为-34-10=-44元。
最后,选择5元硬币,剩余待支付金额为-44-5=-49元。
由于待支付金额已经为负数,我们无法继续选择硬币。
此时,集合中的硬币数为1个50元和3个10元,总共4个硬币。
实验结果:通过贪心算法,我们得到了36元支付所需的最少硬币数为4个。
贪心算法实验报告心得
贪心算法实验报告心得前言贪心算法是一种常见且重要的算法设计思想,通过每一步都选择当下最优的解决方案,以期望最终得到全局最优解。
在学习与实践贪心算法的过程中,我有了许多心得与体会。
什么是贪心算法?贪心算法是一种求解问题的算法思想,它的特点是每一步都选择当前最优的解决方案,而不考虑该选择对以后步骤的影响。
贪心算法通常适用于可以将问题分解为若干个子问题,并且通过每次选择当前最优解来得到整体最优解的情况。
贪心算法的基本步骤贪心算法的基本步骤可以总结为以下几个方面:1.确定问题的解空间,并找到问题的最优解。
贪心算法通常通过穷举法或者利用问题的特殊性质来确定解空间。
2.制定贪心策略。
贪心算法的核心是确定每一步选择的贪心策略,即选择当前最优解。
3.确定贪心策略的正确性。
贪心算法的一个关键问题是如何证明贪心策略的正确性。
可以通过数学证明、反证法或者举反例等方式来进行证明。
4.实现贪心算法。
将贪心策略转化为实际可执行的算法步骤,编写代码来求解问题。
贪心算法实验结果分析在本次实验中,我使用贪心算法解决了一个经典问题:找零钱问题(Change-Making Problem)。
给定一定面额的硬币和需找的金额,我们的目标是使用最少的硬币来完成找零钱。
贪心算法的思路是每次选择面额最大的硬币进行找零。
实验设计1.实验输入:我设计了多组输入来测试贪心算法的性能。
每组输入包括一个需找的金额和一个硬币集合。
2.实验输出:对于每组输入,贪心算法输出一个最优的硬币找零方案,以及使用的硬币数量。
3.实验评价:我使用了实际需找金额与贪心算法计算得到的找零金额的差值来评估算法的准确性,并统计了算法的时间复杂度。
实验结果从多组实验结果中可以观察到,贪心算法在大部分情况下给出了正确的找零金额,并且算法的时间复杂度较低。
结果分析贪心算法在找零钱问题中的应用是合理的。
每次选择面额最大的硬币进行找零,可以快速接近最优解,并且相对其他算法具有较低的时间复杂度。
单源最短路径(贪心法)实验报告
算法分析与设计实验报告第 5 次实验使用贪心法求出给定图各点的最短路径,并计算算法的执行时间,分析算法的有效性。
已知一个有向网络 G=(V,E)和源点 V1,如上所示,求出从源点出发到图中其余顶点的最短路径。
1 用邻接矩阵表示有向图,并进行初始化,同时选择源点;}手动输入实现实验所给图形:随机数产生图的权值:通过这次实验,我回顾了回溯法求解最短路径问题,在其中加入了舍伍德附录:完整代码#include<stdio.h>#include<stdlib.h>#include<time.h>#define maxint 1000int c[200][200]={0};void Dijkstra(int n,int v,int dist[],int prev[]){ bool s[maxint];for(int i=1;i<=n;i++){dist[i]=c[v][i];s[i]=false;if(dist[i]==maxint) prev[i]=0;else prev[i]=v;} //找到第一个可行源点 s[]标志,记录prev[]前一个点dist[v]=0;s[v]=true;for(int i=1;i<n;i++){int temp=maxint;int u=v;for(int j=1;j<=n;j++){if((!s[j])&&(dist[j]<temp)){u=j;temp=dist[j];}}s[u]=true;for(int j=1;j<=n;j++){int newdist=dist[u]+c[u][j];if(newdist<dist[j]){dist[j]=newdist;prev[j]=u;}}}}int main(){int n,v;printf("请输入顶点数: ");scanf("%d",&n);//printf("路径: ");srand(time(0));for(int i=1;i<n+1;i++){for(int j=1;j<n+1;j++){/* scanf("%d",&c[i][j]);*/ ///手动输入if(i!=j){if((c[j][i]==0)||(c[j][i]==1000))c[i][j]=rand()%100+1;else c[i][j]=1000;if(c[i][j]>50) c[i][j]=1000;}}}printf("请输入源点: ");scanf("%d",&v);int dist[n+1],prev[n+1];printf("\n路径:\n");for(int i=1;i<n+1;i++){for(int j=1;j<n+1;j++)printf("%5d ",c[i][j]);printf("\n");}Dijkstra(n,v,dist,prev);for(int i=1;i<n+1;i++){printf("\n%d到%d的最短路径为:%d",v,i,dist[i]);}}。
算法实验报告贪心
一、实验背景贪心算法是一种在每一步选择中都采取当前状态下最好或最优的选择,从而希望导致结果是全局最好或最优的算法策略。
贪心算法并不保证能获得最优解,但往往能获得较好的近似解。
在许多实际应用中,贪心算法因其简单、高效的特点而被广泛应用。
本实验旨在通过编写贪心算法程序,解决经典的最小生成树问题,并分析贪心算法的优缺点。
二、实验目的1. 理解贪心算法的基本原理和应用场景;2. 掌握贪心算法的编程实现方法;3. 分析贪心算法的优缺点,并尝试改进;4. 比较贪心算法与其他算法在解决最小生成树问题上的性能。
三、实验内容1. 最小生成树问题最小生成树问题是指:给定一个加权无向图,找到一棵树,使得这棵树包含所有顶点,且树的总权值最小。
2. 贪心算法求解最小生成树贪心算法求解最小生成树的方法是:从任意一个顶点开始,每次选择与当前已选顶点距离最近的顶点,将其加入生成树中,直到所有顶点都被包含在生成树中。
3. 算法实现(1)数据结构- 图的表示:邻接矩阵- 顶点集合:V- 边集合:E- 已选顶点集合:selected- 最小生成树集合:mst(2)贪心算法实现```def greedy_mst(graph):V = set(graph.keys()) # 顶点集合selected = set() # 已选顶点集合mst = set() # 最小生成树集合for i in V:selected.add(i)mst.add((i, graph[i]))while len(selected) < len(V):min_edge = Nonefor edge in mst:u, v = edgeif v not in selected and (min_edge is None or graph[u][v] < graph[min_edge[0]][min_edge[1]]):min_edge = edgeselected.add(min_edge[1])mst.add(min_edge)return mst```4. 性能分析为了比较贪心算法与其他算法在解决最小生成树问题上的性能,我们可以采用以下两种算法:(1)Prim算法:从任意一个顶点开始,逐步添加边,直到所有顶点都被包含在生成树中。
贪心算法-找零问题 实验报告
实验三课程名称:算法设计与实现实验名称:贪心算法-找零问题实验日期:2019年5月2日仪器编号:007班级:数媒0000班姓名:郝仁学号0000000000实验内容假设零钱系统的币值是{1,p,p^2,……,p^n},p>1,且每个钱币的重量都等于1,设计一个最坏情况下时间复杂度最低的算法,使得对任何钱数y,该算法得到的零钱个数最少,说明算法的主要设计思想,证明它的正确性,并给出最坏情况下的时间复杂度。
实验分析引理1(离散数学其及应用3.1.4):若n是正整数,则用25美分、10美分、5美分和1美分等尽可能少的硬币找出的n美分零钱中,至多有2个10美分、至多有1个5美分、至多有4个1美分硬币,而不能有2个10美分和1个5美分硬币。
用10美分、5美分和1美分硬币找出的零钱不能超过24美分。
证明如果有超过规定数目的各种类型的硬币,就可以用等值的数目更少的硬币来替换。
注意,如果有3个10美分硬币,就可以换成1个25美分和1个5美分硬币;如果有2个5美分硬币,就可以换成1个10美分硬币;如果有5个1美分硬币,就可以换成1个5美分硬币;如果有2个10美分和1个5美分硬币,就可以换成1个25美分硬币。
由于至多可以有2个10美分、1个5美分和4个1美分硬币,而不能有2个10美分和1个5美分硬币,所以当用尽可能少的硬币找n美分零钱时,24美分就是用10美分、5美分和1美分硬币能找出的最大值。
假设存在正整数n,使得有办法将25美分、10美分、5美分和1美分硬币用少于贪心算法所求出的硬币去找n美分零钱。
首先注意,在这种找n美分零钱的最优方式中使用25美分硬币的个数q′,一定等于贪心算法所用25美分硬币的个数。
为说明这一点,注意贪心算法使用尽可能多的25美分硬币,所以q′≤q。
但是q′也不能小于q。
假如q′小于q,需要在这种最优方式中用10美分、5美分和1美分硬币至少找出25美分零钱。
而根据引理1,这是不可能的。
算法分析与设计实验三贪心算法
实验三贪心算法实验目的1. 掌握贪心法的基本思想方法;2. 了解适用于用贪心法求解的问题类型,并能设计相应贪心法算法;3. 掌握贪心算法复杂性分析方法分析问题复杂性。
预习与实验要求1. 预习实验指导书及教材的有关内容,掌握贪心法的基本思想;2. 严格按照实验内容进行实验,培养良好的算法设计和编程的习惯;3. 认真听讲,服从安排,独立思考并完成实验。
实验设备与器材硬件:PC机软件:C++或Java等编程环境实验原理有一类问题是要从所有的允许解中求出最优解,其策略之一是“贪心法”,即逐次实施“贪心选择”:在每个选择步骤上做出的选择都是当前状态下最优的。
贪心选择依赖于在此之前所做出的选择,但不依赖于后续步骤所需要的选择,即不依赖于后续待求解子问题。
显然,这种选择方法是局部最优的,但不是从问题求解的整体考虑进行选择,因此不能保证最后所得一定是最优解。
贪心法是求解问题的一种有效方法,所得到的结果如果不是最优的,通常也是近似最优的。
实验内容以下几个问题选做一项:1. 用贪心法实现带有期限作业排序的快速算法应用贪心设计策略来解决操作系统中单机、无资源约束且每个作业可在等量时间内完成的作业调度问题。
假定只能在一台机器上处理N个作业,每个作业均可在单位时间内完成;又假定每个作业i都有一个截止期限di>0(它是整数),当且仅当作业i在它的期限截止以前被完成时,则获得pi的效益。
这个问题的一个可行解是这N个作业的一个子集合J,J中的每个作业都能在各自的截止期限之前完成。
可行解的效益值是J中这些作业的效益之和,即Σp。
具有最大效益值的可行解就是最优解。
2. 实现K元归并树贪心算法两个分别包含n个和m个记录的已分类文件可以在O(n+m)时间内归并在一起而得到一个分类文件。
当要把两个以上的已分类文件归并在一起时,可以通过成对地重复归并已分类的文件来完成。
例如:假定X1,X2,X3,X4是要归并的文件,则可以首先把X1和X2归并成文件Y1,然后将Y1和X3归并成Y2,最后将Y2和X4归并,从而得到想要的分类文件;也可以先把X1和X2归并成Y1,然后将X3和X4归并成Y2,最后归并Y1和Y2而得到想要的分类文件。
找零问题贪心算法实现
找零问题贪心算法实现一、实验描述当前有面值分别为2角5分,1角,5分,1分的硬币,请给出找n分钱的最佳方案(要求找出的硬币数目最少)。
二、实验原理具体实例:假如老板要找给我99分钱,他有上面的面值分别为25,10,5,1的硬币数,为了找给我最少的硬币数,那么他是不是该这样找呢,先看看该找多少个25分的, 99/25=3,好像是3个,要是4个的话,我们还得再给老板一个1分的,我不干,那么老板只能给我3个25分的拉,由于还少给我24,所以还得给我2个10分的和4个1分。
具体实现:<<endl;outputFile<<setw(4)<<"面值"<<setw(7)<<"个数"<<endl;int sum=0;for (int i=1;i<=number;i++){ inputFile>>T[i];inputFile>>Coins[i];outputFile<<setw(3)<<T[i]<<setw(3)<<" "<<setw(3)<<Coins[i]<<endl;sum+=T[i]*Coins[i];}inputFile>>TotalMoney;outputFile<<"需要找回的总钱数为: "<<TotalMoney<<endl;if (T!=NULL && Coins!=NULL){ if (sum>=TotalMoney)return true;else outputFile<<"所有硬币的总钱数是"<<sum<<" 小于需要找回的总钱数"<<TotalMoney<<endl;return false;}return false;}int LeastCoins::changeMoney(int i,int j){ if (i>1){ if (j<T[i]) // 要找的钱数小于该硬币的面值{m[i-1][j]=changeMoney(i-1,j);m[i][j]=m[i-1][j]; return m[i][j]; }else{ int X=j/T[i];X=(X<Coins[i] X : Coins[i]) ;int T1=changeMoney(i-1,j-X*T[i]);int T2=changeMoney(i-1,j-(X-1)*T[i]);m[i-1][j-X*T[i]]=T1;m[i-1][j-(X-1)*T[i]]=T2;if ((T1+X)>(T2+X-1)) m[i][j]=T2+X-1;else m[i][j]=T1+X;return m[i][j];}}else if(i==1)// 此时 i==1{ if ((j%T[1])==0 && (j/T[1]<=Coins[1])){ m[1][j]=j/T[1]; return m[1][j]; } else return 1000000;}else return 1000000;}void LeastCoins::output(){ if (m[number][TotalMoney]<1000000) // 判断是否有解{ outputFile<<"需要最少的硬币个数是: "<<m[number][TotalMoney]<<endl;outputFile<<setw(4)<<"面值"<<setw(7)<<"个数"<<endl;traceback();}else outputFile<<"无解"<<endl;}void LeastCoins::traceback(){int j=TotalMoney;for (int i=number;i>=2;i--){int X=j/T[i]; // 最多需要面值为 T[i] 的硬币的个数X=(X<Coins[i] X : Coins[i]) ; // 取 X 和 Coins[i]的较小值int T1=m[i-1][j-X*T[i]]+X;int T2=m[i-1][j-(X-1)*T[i]]+X-1;if (T1<T2){ outputFile<<setw(3)<<T[i]<<setw(3)<<" "<<setw(3)<<X<<endl; j-=X*T[i]; } else { outputFile<<setw(3)<<T[i]<<setw(3)<<" "<<setw(3)<<(X-1)<<endl;j-=(X-1)*T[i]; }}outputFile<<setw(3)<<T[i]<<setw(3)<<" "<<setw(3)<<(j/T[1])<<endl;}int main(){ LeastCoins LC;();return 0;}三、运行结果图1 运行结果四、实验总结对贪心算法不是特别熟悉,以至于在编写程序时遇到好多错误,好在差不多都改正了,此程序尚有不足之处,希望在以后的深入学习后能编写个更好的程序。
贪心算法_实验报告
贪心算法_实验报告一、设计分析●问题描述:键盘输入一个高精度的正整数N(N不超过240位),去掉其中任意S个数字后剩下的数字按原左右次序将组成一个新的正整数。
编程对给定的N和S,寻找一种方案使得剩下的数字组成的新数最小。
●设计思路:在位数固定的前提下,让高位的数字尽量小其值就较小,依据此贪心策略解决此问题。
删除高位较大的数字。
具体:相邻两位比较若高位比低位大则删除高位。
删除字符的方法:1)物理删除,用后面的字符覆盖已删除的字符。
有比较多字符移动操作,算法效率不高。
2)用数组记录字符的状态,“1”表示对应数字存在,“0”表示对应数字已删除。
3)利用数组,记录未删除字符的下标:n=“1 2 4 3 5 8 3 3”0 0 0 0 0 04比3大删除“1 2 3 5 8 3 3” 1 2 4 5 0 08比3大删除“1 2 3 5 3 3” 1 2 4 5 05比3大删除“1 2 3 3 3” 1 2 4 7 8二、程序代码c语言实现#include<stdio.h>#include<string.h>#define N 10000int main(void){char a[N];int i,j,k,n;printf("输入要处理的数据:\n");gets(a);printf("输入要删除的数字个数:\n");scanf("%d",&n);三、测试用例四、实验总结加深了对贪心算法的理解与运用。
所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。
这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
人民币找零问题
证明人民币找零问题的贪心算法的正确性1.问题的提出日常生活当中, 买卖东西的时候经常遇到找零钱问题, 例如超市购物付款时,收银员就会根据收款机给顾客找零钱。
我们不难发现收银员找零时,总是先支付顾客最大面值的人民币, 要是金额不足再支付面值小一点的, 直到找满为止。
很显然,这样的找零方法符合贪心方法,但是收银员用这样的贪心方法找给顾客零钱时,是否就能使零钱的张数达到最少?有没有更好的策略,使张数比用贪心方法的更少?这个问题就有待我们考证。
2.贪心算法的含义贪心算法是一种能够得到某种度量意义下的最优解的分级处理方法, 它总是做出在当前看来是最优的选择, 也就是说贪心策略并不是从整体上加以考虑, 它所做出的选择只是在某种意义上的局部最优解算法。
3.贪心算法的基本要素贪心算法通过一系列的选择来得到问题的解。
它所做的每一个选择都是当前状态下局部最好选择,即贪心选择。
但是,从许多可以用贪心算法求解的例子中看到这类问题一般具有2个重要的性质:贪心选择性质和最优子结构性质。
3.1 贪心选择性质所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。
这是贪心算法可行的第一个基本要素。
贪心算法是以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
3.2 最优子结构性质当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。
4.贪心算法的基本思路及实现的过程4.1贪心算法的基本思路贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行, 根据某个优化测度, 每一步都要确保能获得局部最优解。
每一步只考虑一个数据, 他的选取应该满足局部优化的条件。
若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中, 直到把所有数据枚举完, 或者不能再添加算法停止。
实验3 贪心算法
淮海工学院计算机工程学院实验报告书课程名:《算法分析与设计》题目:实验3 贪心算法班级:学号:姓名:实验3 贪心算法实验目的和要求(1)了解前缀编码的概念,理解数据压缩的基本方法;(2)掌握最优子结构性质的证明方法;(3)掌握贪心法的设计思想并能熟练运用(4)证明哈夫曼树满足最优子结构性质;(5)设计贪心算法求解哈夫曼编码方案;(6)设计测试数据,写出程序文档。
实验内容设需要编码的字符集为{d 1, d 2, …, dn },它们出现的频率为{w 1, w 2, …, wn },应用哈夫曼树构造最短的不等长编码方案。
实验环境Turbo C 或VC++实验学时2学时,必做实验数据结构与算法//构造哈夫曼结构体struct huffman{double weight; //用来存放各个结点的权值int lchild,rchild,parent; //指向双亲、孩子结点的指针 };核心源代码#include<iostream>#include <string>using namespace std;#include <stdio.h>//构造哈夫曼结构体struct huffman{double weight;∑=j i k k aint lchild,rchild,parent;};static int i1=0,i2=0;//选择权值较小的节点int Select(huffman huff[],int i){int min=11000;int min1;for(int k=0;k<i;k++){if(huff[k].weight<min && huff[k].parent==-1){min=huff[k].weight;min1=k;}}huff[min1].parent=1;return min1;}//定义哈夫曼树,并对各个节点进行赋权值void HuffmanTree(huffman huff[],int weight[],int n) {for(int i=0;i<2*n-1;i++){huff[i].lchild=-1;huff[i].parent=-1;huff[i].rchild=-1;}for(int l=0;l<n;l++){huff[l].weight=weight[l];}for(int k=n;k<2*n-1;k++){int i1=Select(huff,k);int i2=Select(huff,k);huff[i1].parent=k;huff[i2].parent=k;huff[k].weight= huff[i1].weight+huff[i2].weight;huff[k].lchild=i1;huff[k].rchild=i2;}}//哈夫曼编码,左0右1void huffmancode(huffman huff[],int n){string s;int j;for(int i=0;i<n;i++){s="";j=i;while(huff[j].parent!=-1){if(huff[huff[j].parent].lchild==j)s=s+"0";else s=s+"1";j=huff[j].parent;}cout<<"第"<<i+1<<"个节点的哈夫曼编码为:";for(int j=s.length();j>=0;j--){cout<<s[j];}cout<<endl;}}void main(){huffman huff[20];int n,w[20];printf("请输入节点的个数:");scanf("%d",&n);for(int i=0;i<n;i++){printf("请输入第%d个节点的权值:",i+1);scanf("%d",&w[i]);}printf("\n");HuffmanTree(huff,w,n);huffmancode(huff,n);}实验结果实验体会本次实验是用贪心法求解哈夫曼编码,其实贪心法和哈夫曼树的原理是一样的,每次将集合中两个权值最小的二叉树合并成一棵新二叉树,每次选择两个权值最小的二叉树时,规定了较小的为左子树。
贪心算法实验报告
typedef struct node{
int id ,time;//作业所需时间
}jobnode;
typedef struct Node{
int id ,avail;//id机器编号、avail每次作业的初始时间
}manode;
manode machine[N];
jobnode job[N];
scanf("%d",&n);
printf("请输入加油站的个数:");
scanf("%d",&k);
for(i=0;i<=k;i++)
scanf("%d",&d[i]);
greedy(d,n,k);
}
实验结果截图:
(3)实验代码:设有n个正整数,将它们连接成一排,组成一个最大的多位整数
#include<stdio.h>
return;
}
}
for(i=0,s=0;i<=k;i++){
if(s<n)
s+=d[i];
else if(s>n){
n=s-d[i];
num++;
}
}
printf("%d\n",num);
}
void main(){
int i,n,k;
int d[1000];
printf("请输入汽车可行驶公里数:");
/*找出下一个作业执行机器*/
manode *Find_min(manode a[],int m){
manode *temp=&a[0];
贪心算法实验报告
一、实验目的通过本次实验,使学生对贪心算法的概念、基本要素、设计步骤和策略有更深入的理解,掌握贪心算法的原理和应用,并能够运用贪心算法解决实际问题。
二、实验内容本次实验主要涉及以下两个问题:1. 使用贪心算法解决单起点最短路径问题;2. 使用贪心算法解决小船过河问题。
三、实验原理1. 贪心算法贪心算法(又称贪婪算法)是一种在每一步选择中都采取当前最优的选择,从而希望导致结果是全局最优的算法。
贪心算法在每一步只考虑当前的最优解,不保证最终结果是最优的,但很多情况下可以得到最优解。
2. 单起点最短路径问题单起点最短路径问题是指在一个有向无环图中,从某个顶点出发,找到到达其他所有顶点的最短路径。
3. 小船过河问题小船过河问题是指一群人需要划船过河,船只能容纳两个人,过河后需要一人将船开回,问最少需要多久让所有人过河。
四、实验步骤及说明1. 创建图结构,包括顶点数组和边信息。
2. 使用Dijkstra算法求解单起点最短路径问题,得到最短路径和前驱顶点。
3. 使用贪心算法找到两点之间的最短距离,并更新距离和前驱顶点信息。
4. 遍历所有顶点,找到未纳入已找到点集合的距离最小的顶点,并更新其距离和前驱顶点。
5. 最终输出从源顶点到达其余所有点的最短路径。
6. 使用贪心算法解决小船过河问题,按照以下步骤进行:(1)计算所有人过河所需的总时间;(2)计算每次划船往返所需时间;(3)计算剩余人数;(4)重复(2)和(3)步骤,直到所有人过河。
五、实验结果与分析1. 单起点最短路径问题实验中,我们选取了有向无环图G,其中包含6个顶点和8条边。
使用贪心算法和Dijkstra算法求解单起点最短路径问题,得到的实验结果如下:- 贪心算法求解单起点最短路径问题的时间复杂度为O(V^2),其中V为顶点数;- Dijkstra算法求解单起点最短路径问题的时间复杂度为O(V^2),其中V为顶点数。
2. 小船过河问题实验中,我们选取了一群人数为10的人过河,船每次只能容纳2人。
贪心算法实验小结
贪心算法实验小结
最近,我和我的同学们在实验室里进行了一次关于贪心算法的实验,探究贪心算法在旅行商问题中的应用。
实验的准备工作非常简单,我们只需要准备好实验所需的数据,并将其输入到计算机中即可。
之后,我们使用贪心算法来解决这个旅行商问题,运用贪心思想,在遍历所有城市时,选择当前停留时间最短的城市作为下一站,以期最终获得最短的旅行路线。
实验的过程中,我们发现,贪心算法可以有效地解决旅行商问题,即使在城市数量较多的情况下,它仍然能够在较短的时间内得到最优解。
除了旅行商问题之外,贪心算法还可以应用于其他许多其他问题,比如背包问题,最大化问题等。
在这次实验中,我们研究到了贪心算法的原理和应用,对于贪心算法在求解复杂问题中的重要性有了更深的认识。
此外,我们也体会到了贪心算法的局限性,它只能获得局部最优解,而不能保证全局最优解。
总之,本次实验对我们的研究有很大的帮助,不仅加深了对贪心算法的认识,而且还能够更好地理解其在实际问题中的应用,让我们更加清楚如何有效地利用贪心算法来解决复杂问题。
贪心算法实验报告(C语言)
实验2、《贪心算法实验》一、实验目的1. 了解贪心算法思想2. 掌握贪心法典型问题,如背包问题、作业调度问题等。
二、实验内容1. 编写一个简单的程序,实现单源最短路径问题。
2. 编写一段程序,实现找零。
【问题描述】当前有面值分别为2角5分,1角,5分,1分的硬币,请给出找n分钱的最佳方案(要求找出的硬币数目最少)。
3. 编写程序实现多机调度问题【问题描述】要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m 台机器加工处理完成。
约定,每个作业均可在任何一台机器上加工处理,但未完工前不允许中断处理。
作业不能拆分成更小的子作业。
三、算法思想分析1.初始化将源点设计为红点集,其余点设计为蓝点,重复选择蓝点集中与源点路径最短的点加入红点集,更新剩余的蓝点集路径,直至蓝点集为空或者只剩下没有连通的点,那么源点到其余所有点的最短路径就出来了。
2.找零问题是典型的贪心问题,但是并不代表所有的找零都能用贪心算法找到最优解。
只有满足贪心选择性质的找零才能找到最优解,本题满足贪心选择性质,直接先一直选面值最大的硬币,再一次减小即可。
3.先对作业按时长进行重排序,再依次找目前用时最短的机器安排工作并加上对应时长,最后总时长为机器中用时最长的那个时长。
四、实验过程分析1.单源最短路径的算法思想并不难,但是在实际编码过程中还是有很多小问题需要注意,首先,一定要新建数组存储路径变化,因为后面计算路径时会用到原数组,如果直接在原数组上更改后面就找不到原数据了,那么就会出现偏差。
其次就是建议先写个伪代码,判断的if-else语句比较多,容易搞混,在代码中一定要及时备注,某些代码的功能是什么,不然再次看代码时需要思考很久甚至忘记。
2.找零问题直接用while循环或者不断取余取模即可解决。
3.作业调度问题大致分为三步,一是排序,二是不断找最短时长的机器安排作业,三是找最长时间为作业完成时间。
五、算法源代码及用户屏幕1.(1)算法源码/**********************单源最短路径问题。
贪心算法概述及研讨
对贪心算法的概述和研讨福州第一中学高一(8)班汪涛指导老师:陈颖算法总览当一个问题具有“最优子结构”时,我们可以采用动态规划法解决该问题。
但是有的时候,贪心算法可以更好的处理该类问题。
总体上看,贪心算法是一种高效的、不稳定的算法;但是它在解决问题时有很多独特的优良性质,掌握贪心算法有时可以非常迅速的获得最优解或近似最优解。
关键字:贪心算法(贪婪算法),贪心算法的应用举例,Object Pascal,快速算法,不稳定算法,信息学奥赛。
何时采用何时能,又何时应该采用贪心算法呢?一般认为,凡是经过数学归纳法证明可以采用贪心算法的情况,都应该采用它。
因为它的效率是很高的。
贪心算法的弱点在于它的不稳定性,即有时它不总能返回最优解。
那么能采用贪心算法的问题具有怎样的性质呢?(何时采用贪心算法)1、它具有和动态规划问题相似的性质,即分治法中的“最优子结构”性质,即每个子问题的最优解的集合就是整体最优解。
这是必须的性质,因为贪心算法解决的问题流程就需要依序研究每个子问题,然后综合之得出最后结果。
不能采用分治法解决的问题,是理论上是不能使用贪心算法的。
而且,必须拥有最优子结构性质,才能保证贪心算法返回最优解。
2、它必须具有一种特殊的“贪心选择性”。
这种性质类同于“最优子结构”性质,但又有一些小的差别。
我们知道,在动态规划中,每一个父问题结果的得出需要它的子问题作为条件;但是“贪心选择性”则不需要;贪心选择性所做的是一个非线性的子问题处理过程,即一个子问题并不依赖于另一个子问题,但是子问题间有严格的顺序性。
要证明一个问题具有“贪心选择性”,就必须证明每一步所做的贪心选择最终导致一个问题的整体最优解。
这也是必须的性质。
如果一个问题具有上述两个性质,理论上就应该采用贪心算法。
处理流程经由贪心算法处理的问题需要经过排序。
即把“最贪心”的子结果排在序列的最前面,一直到“最不贪心的”。
这是处理问题的第一步。
然后依序解决问题而得出最终结果。
找零钱问题算法报告
《找零钱》实验报告目录一. 问题描述1. 问题描述 (2)二.算法描述与分析1. 找零钱问题算法伪代码 (3)2. 算法分析 (5)三.实验结果与分析1. 实验环境 (5)2. 实验的执行 (5)3.实验结果 (6)4.找零钱的其他情况 (6)四.总结与展望1. 总结 (8)2. 展望 (8)3.任务分工 (8)五.代码1. 贪婪技术 (8)2. 动态规划 (10)1问题描述一个小孩买了价值少于1美元的糖,假设需要找给小孩n美分。
不过他的钱包里只有1美元,于是他将1美元的钱交给售货员。
收银台有数目不限的硬币,面值分别为25美分、10美分、5美分、及1美分,如果售货员希望用数目最少的硬币找给小孩,要求设计算法,使得售货员以最少的硬币数,用25、10、5、1美分凑齐n美分。
(n<100)要求通过该问题,掌握贪心算法和动态规划算法的具体实现步骤,理解算法的基本思想,加深巩固对解决问题的思路和方法。
其中,考虑到需要解决问题的方法具有普遍适用性,该题着重动态规划算法的实现。
找零钱问题是动态规划经典题目之一。
该问题的求解方法,可类比于背包问题(The Knapsack Problem)的求解。
图1 动态规划2算法描述与分析假设零钱的面额为v1, v2,..., v m(面额升序排列),需要给出w元的找零,使用各面额的零钱的数量为n1,n2,...,n m.贪心技术解决找零钱问题的思想:想要找补的零钱数量最少,肯定优先使用面额大的零钱。
(1)将零钱按照面额大小排序;(2)总是尝试用当前面额最大的零钱来找补,在不超过需要找补的总额的条件下,尽可能的多用当前面额最大的零钱,并计算出剩余的需要找补的总额;(3)没有达到需要找补的总额的情况下,重复步骤(2)直到达到需要找补的总额。
贪心技术解决找零钱问题的正确性证明:使用贪心技术解决找零钱问题得到最优解对零钱的面额是有要求的,对于零钱面额为c 0, c 1,..., c m (其中c >1,m ≥1)的找零问题,使用贪心技术是可以得到最优解的,证明如下:假设需要找零w 元,对于此问题未使用贪心技术得到的一个最优解S ,使用面额为c i 的零钱数量为n i ,则n i ≤c −1;如果n i ≥c ,则可以使用面值为c i+1的零钱找补,使所用的零钱数量比最优解少,出现矛盾。
实验三贪心算法
实验三:贪心算法一、实验目的(1)理解贪心算法的基本思想;(2)熟悉多机调度问题的算法;(3)初步掌握贪心算法的应用。
二、实验环境微型计算机,WindowXP , Visual C++6.0三、实验内容要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。
约定每个作业均可在任何一台机器上加工处理,但未完工前不允许中断处理。
作业不能拆分成更小的子作业。
四、实验结果五、源代码#include <stdio.h>#define M 100void main(){int i,j,k,temp,m,n;int t[M]={2,14,4,16,6,5,3},p[M]={1,2,3,4,5,6,7},s[M],d[M]={0};m=3;n=7;for(i=0;i<7;i++)for(j=0;j<7-i;j++)if(t[j]<t[j+1]) //排序使t[]由大到小{temp=t[j];t[j]=t[j+1];t[j+1]=temp;temp=p[j]; //p[]始终和t[]一一对应p[j]=p[j+1];p[j+1]=temp;}for(i=0;i<m;i++) //求时间。
{s[i]=p[i];d[i]=t[i];}for(k=0;k<m;k++)printf(" %d",d[k]);printf("\n");for(i=m;i<n;i++){for(k=0;k<m-1;k++) //求最小。
{temp=d[k];if(temp>d[k+1]){temp=d[k+1];j=k+1;}}printf("这是最小下标的:%d\n",j);printf("最小的值:%d\n",temp);for(k=0;k<m;k++)printf(" %d",d[k]);printf("\n");//j=temp;s[j]=s[j]+p[i];d[j]=d[j]+t[i];}printf("\n");for(k=0;k<7;k++)printf(" %d",t[k]);printf("\n");for(k=0;k<7;k++)printf(" %d",p[k]);printf("\n");for(k=0;k<m;k++)printf(" %d",s[k]);printf("\n");for(k=0;k<m;k++)printf(" %d",d[k]);printf("\n");}。
贪心算法实验报告
贪心算法实验报告贪心算法实验报告引言:贪心算法是一种常用的算法设计思想,它在求解最优化问题中具有重要的应用价值。
本实验报告旨在介绍贪心算法的基本原理、应用场景以及实验结果,并通过实例加以说明。
一、贪心算法的基本原理贪心算法是一种以局部最优解为基础,逐步构建全局最优解的算法。
其基本原理是在每一步选择中都采取当前状态下最优的选择,而不考虑之后的结果。
贪心算法通常具备以下特点:1. 贪心选择性质:当前状态下的最优选择一定是全局最优解的一部分。
2. 最优子结构性质:问题的最优解可以通过子问题的最优解来构造。
3. 无后效性:当前的选择不会影响以后的选择。
二、贪心算法的应用场景贪心算法适用于一些具有最优子结构性质的问题,例如:1. 路径选择问题:如Dijkstra算法中的最短路径问题,每次选择当前距离最短的节点进行扩展。
2. 区间调度问题:如活动选择问题,每次选择结束时间最早的活动进行安排。
3. 零钱找零问题:给定一些面额不同的硬币,如何用最少的硬币凑出指定的金额。
三、实验设计与实现本次实验选择了一个经典的贪心算法问题——零钱找零问题,旨在验证贪心算法的有效性。
具体实现步骤如下:1. 输入硬币面额和需要凑出的金额。
2. 对硬币面额进行排序,从大到小。
3. 从面额最大的硬币开始,尽可能多地选择该面额的硬币,直到不能再选择为止。
4. 重复步骤3,直到凑出的金额等于需要凑出的金额。
四、实验结果与分析我们通过对不同金额的零钱找零问题进行实验,得到了如下结果:1. 当需要凑出的金额为25元时,贪心算法的结果为1个25元硬币。
2. 当需要凑出的金额为42元时,贪心算法的结果为1个25元硬币、1个10元硬币、1个5元硬币、2个1元硬币。
3. 当需要凑出的金额为63元时,贪心算法的结果为2个25元硬币、1个10元硬币、1个1元硬币。
通过实验结果可以看出,贪心算法在零钱找零问题中取得了较好的效果。
然而,贪心算法并不是适用于所有问题的万能算法,它的有效性取决于问题的特性。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验三
课程名称:算法设计与实现实验名称:贪心算法-找零问题
实验日期:2019年5月2日仪器编号:007
班级:数媒0000班姓名:郝仁学号0000000000
实验内容
假设零钱系统的币值是{1,p,p^2,……,p^n},p>1,且每个钱币的重量都等于1,设计一个最坏情况下时间复杂度最低的算法,使得对任何钱数y,该算法得到的零钱个数最少,说明算法的主要设计思想,证明它的正确性,并给出最坏情况下的时间复杂度。
实验分析
引理1(离散数学其及应用3.1.4):若n是正整数,则用25美分、10美分、5美分和1美分等尽可能少的硬币找出的n美分零钱中,至多有2个10美分、至多有1个5美分、至多有4个1美分硬币,而不能有2个10美分和1个5美分硬币。
用10美分、5美分和1美分硬币找出的零钱不能超过24美分。
证明如果有超过规定数目的各种类型的硬币,就可以用等值的数目更少的硬币来替换。
注意,如果有3个10美分硬币,就可以换成1个25美分和1个5美分硬币;如果有2个5美分硬币,就可以换成1个10美分硬币;如果有5个1美分硬币,就可以换成1个5美分硬币;如果有2个10美分和1个5美分硬币,就可以换成1个25美分硬币。
由于至多可以有2个10美分、1个5美分和4个1美分硬币,而不能有2个10美分和1个5美分硬币,所以当用尽可能少的硬币找n美分零钱时,24美分就是用10美分、5美分和1美分硬币能找出的最大值。
假设存在正整数n,使得有办法将25美分、10美分、5美分和1美分硬币用少于贪心算法所求出的硬币去找n美分零钱。
首先注意,在这种找n美分零钱的最优方式中使用25美分硬币的个数q′,一定等于贪心算法所用25美分硬币的个数。
为说明这一点,注意贪心算法使用尽可能多的25美分硬币,所以q′≤q。
但是q′也不能小于q。
假如q′小于q,需要在这种最优方式中用10美分、5美分和1美分硬币至少找出25美分零钱。
而根据引理1,这是不可能的。
由于在找零钱的这两种方式中一定有同样多的25美分硬币,所以在这两种方式中10美分、5美分和1美分硬币的总值一定相等,并且这些硬币的总值不超过24美分。
10美分硬币的个数一定相等,因为贪心算法使用尽可能多的10美分硬币。
而根据引理1,当使用尽可能少的硬币找零钱时,至多使用1个5分硬币和4个1分硬币,所以在找零钱的最优方式中也使用尽可能多的10美分硬币。
类似地,5美分硬币的个数相等;最终,1美分的个数相等。
同上,由于1+p1+p2+p3+...pk-1=pk - 1<pk,故当n大于pk时,可以分解为pk与n-pk的值,其中pk只用一个硬币值为pk的硬币就能得到最少硬币数,而子问题变成n-pk的最少硬币数,依次类推,贪心算法总能得到最好的结果。
假若最优解不含币值j
p 的钱币,即112210--+⋯+++=j j p x p x p x x y 那么存在{}1,1,0,-⋯∈≥j i p x i ,,如果不是,则
11)(1(12112210-=+⋯+++-≤+⋯+++=---j j j j p p p p p p x p x p x x y
与j p ≥y 矛盾,不妨设p x i ≥,那么用1个币值为1+i p 的钱币替换p 个币值为j
p 的钱币,总钱币数将减少1-p ,与这个解为最优解矛盾。
下面证明最优解签好含有⎣⎦
j p /y 个币值j p 的钱币。
设钱数为y 时最优解是()y F j ,则
()()
()⎪⎩⎪⎨⎧<≥+-=-j j j j j j p y y F p y p y F y F 11 设()j j p tp y <+=δδ其中⎣⎦j
p y t /= 通过对t 的归纳不难证明()()δ1
j -+=j F t y F ,即最优解中含有⎣⎦
j p y /个币值j p 的钱币。
上诉算法在最坏情况下的时间复杂度是()()}log ,m in{y n O n W =.
实验源代码
// 找零ConsoleApplication1.cpp : 此文件包含 "main" 函数。
程序执行将在此处开始并结束。
//数媒1703班-1191170329-唐思成
// coin.cpp : 定义控制台应用程序的入口点。
//
#include "pch.h"
#include <iostream>
#include <math.h>
using namespace std;
//money 需要找零的钱
//coin 可用的硬币的种类
//n 硬币种类的数量
void ZhaoLing(int money , int *coin , int n ){
int *coinNum = new int [money + 1]();//存储1...money 找零最少需要的硬币的个数
int *coinValue = new int [money + 1]();//最后加入的硬币,方便后面输出是哪几个硬币 coinNum[0] = 0;
for (int i = 1; i <= money; i++)
{
int minNum = i;//i面值钱,需要最少硬币个数
int usedMoney = 0;//这次找零,在原来的基础上需要的硬币
for (int j = 0; j < n; j++)
{
if (i >= coin[j])//找零的钱大于这个硬币的面值
{
if (coinNum[i - coin[j]] + 1 <= minNum && (i == coin[j] || coinValue[i - coin[j]] != 0))//所需硬币个数减少了
{
minNum = coinNum[i - coin[j]] + 1;//更新
usedMoney = coin[j];//更新
}
}
}
coinNum[i] = minNum;
coinValue[i] = usedMoney;
}
//输出结果
if (coinValue[money] == 0)
cout <<"找不开零钱"<< endl;
else
{
cout <<"需要最少硬币个数为:"<< coinNum[money] << endl;
cout <<"硬币分别为:";
while (money > 0)
{
cout << coinValue[money] <<",";
money -= coinValue[money];
}
cout << endl;
}
delete[]coinNum;
delete[]coinValue;
}
int main(){
int Money;
int n,i,p;
cout <<"请输入需要找零的钱的值"<< endl;
cin >> Money;
cout <<"请输入硬币种类的数量"<< endl;
cin >> n;
int*coin = (int*)malloc(n * sizeof(int));//定义动态长度的数组
cout <<"请输入零钱的底数"<< endl;
while(1) {
cin >> p;
if (p > 0) {
break;
}
else {
cout <<"输入的数小于零,请重新输入"<< endl;
}
}
for (i = 0; i < n; i++) {
coin[i] = pow(p, i);
}
cout <<"找零系统中的零钱种类为:"<< endl;
for (i = 0; i < n; i++) {
cout << coin[i] <<",";
}
cout << endl;
ZhaoLing(Money, coin, n);
system("pause");
return 0;
}
实验结果。