找零问题贪心算法实现
证明人民币找零问题贪心算法正确性

证明人民币找零问题贪心算法的正确性问题提出:根据人们生活常识,我们到商店里买东西需要找零钱时,收银员总是先给我们最大面值的,要是不够再找面值小一点的,直到找完为止。
这就是一个典型的贪心选择问题。
问题描述:当前有面值分别为100 元、50 元、20 元、10 元、5元、1元, 5角, 2角、1角的人民币。
证明人民币在找零时(1-99元)符合贪心算法,即证明此问题满足贪心算法的两个基本要素:即最优子结构性质和贪心选择性质。
问题证明:当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
在人民币找零问题中,其最优子结构性质表现为:设c[i]是各面额人民币使用的数量,S[i]是商品价格为n时的最优解,数量为K。
现在设某面值的人民币数量减一:S[j]=S[j]-1,则新的S[i]为n-c[j]的最优解,纸币数K-1. 否则,设T[i]是n-c[j]的最优解,纸币数为m,即m<k-1.那么对于n来说,T[i]+1应该为原问题最少纸币数,即m+1<k-1+1=k,此与k为最少纸币数矛盾,故问题满足最优子结构性质。
贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。
在人民币找零问题中,满足贪心选择性质的证明如下:设纸币面额100,50,20,10,5,2,1元的数量依次为A,B,C,D,E,F,G,则根据贪心算法思想得到的解应依次保证max(A),max(B),max(C),max(D),max(E),max(F),max(G)。
假设存在更优的算法,使得所用的纸币数更少,即数量至少小于或等于A+B+C+D+E+F+G-1。
那么在纸币总数减少的情况下保证总额不变只能增大相对大面额纸币的数量并减少小面额纸币数量。
而由贪心算法知max(A)已经是最大的了,以此类推,max(B),max(C),max(D),max(E),max(F)均应为最大数量了,所以贪心算法得到的解是最优解,即满足贪心选择性质。
python贪心算法的实现

python贪⼼算法的实现贪⼼算法贪⼼算法(⼜称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。
也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。
贪⼼算法不是对所有问题都能得到整体最优解,关键是贪⼼策略的选择,选择的贪⼼策略必须具备⽆后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
基本思路思想贪⼼算法的基本思路是从问题的某⼀个初始解出发⼀步⼀步地进⾏,根据某个优化测度,每⼀步都要确保能获得局部最优解。
每⼀步只考虑⼀个数据,他的选取应该满⾜局部优化的条件。
若下⼀个数据和部分最优解连在⼀起不再是可⾏解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加算法停⽌。
步骤1. 遍历初始集合X中的备选元素2. 利⽤贪⼼策略在X中确定⼀个元素,并将其加⼊到可⾏解S中3. 得到可⾏解SP即为贪⼼策略,⽤来选择符合条件的元素。
例⼦——硬币找零假设某国硬币⾯值有1,5,10,25,100元五种⾯额,若店员为顾客找零时,需要给顾客找零a=36元,求硬币数最少的情况。
这⾥我们的贪⼼策略为:先找到最接近a的值,然后对a进⾏更新,然后进⾏循环。
代码实现def shortNum(a):coins = [1,5,10,25,100]out = []coins = coins[::-1]for i in coins:num = a//iout=out+[i,]*numa = a-num*iif a<=0:breakreturn outa = 36print(shortNum(a))例⼦——任务规划问题描述:输⼊为任务集合X= [r1,r2,r3,...,rn],每个任务ri,都对应着⼀个起始时间ai与结束时间bi要求输出为最多的相容的任务集。
如上图,r1与r2相容,r3与r1和r2都不相容。
那么这⾥的贪⼼策略我们可以设为:1. 先将结束时间最短的任务加⼊到S中,2. 再从剩下的任务的任务中选择结束时间最短的,且判断与S集合中的任务是否相容3. 若不相容,则换下⼀个时间最短的任务,并进⾏⽐较4. 循环,直⾄X为空。
贪心算法实验报告心得

贪心算法实验报告心得前言贪心算法是一种常见且重要的算法设计思想,通过每一步都选择当下最优的解决方案,以期望最终得到全局最优解。
在学习与实践贪心算法的过程中,我有了许多心得与体会。
什么是贪心算法?贪心算法是一种求解问题的算法思想,它的特点是每一步都选择当前最优的解决方案,而不考虑该选择对以后步骤的影响。
贪心算法通常适用于可以将问题分解为若干个子问题,并且通过每次选择当前最优解来得到整体最优解的情况。
贪心算法的基本步骤贪心算法的基本步骤可以总结为以下几个方面:1.确定问题的解空间,并找到问题的最优解。
贪心算法通常通过穷举法或者利用问题的特殊性质来确定解空间。
2.制定贪心策略。
贪心算法的核心是确定每一步选择的贪心策略,即选择当前最优解。
3.确定贪心策略的正确性。
贪心算法的一个关键问题是如何证明贪心策略的正确性。
可以通过数学证明、反证法或者举反例等方式来进行证明。
4.实现贪心算法。
将贪心策略转化为实际可执行的算法步骤,编写代码来求解问题。
贪心算法实验结果分析在本次实验中,我使用贪心算法解决了一个经典问题:找零钱问题(Change-Making Problem)。
给定一定面额的硬币和需找的金额,我们的目标是使用最少的硬币来完成找零钱。
贪心算法的思路是每次选择面额最大的硬币进行找零。
实验设计1.实验输入:我设计了多组输入来测试贪心算法的性能。
每组输入包括一个需找的金额和一个硬币集合。
2.实验输出:对于每组输入,贪心算法输出一个最优的硬币找零方案,以及使用的硬币数量。
3.实验评价:我使用了实际需找金额与贪心算法计算得到的找零金额的差值来评估算法的准确性,并统计了算法的时间复杂度。
实验结果从多组实验结果中可以观察到,贪心算法在大部分情况下给出了正确的找零金额,并且算法的时间复杂度较低。
结果分析贪心算法在找零钱问题中的应用是合理的。
每次选择面额最大的硬币进行找零,可以快速接近最优解,并且相对其他算法具有较低的时间复杂度。
贪心算法——找零钱问题

f(num-10,n10+1,n5,n1); } else if(num>=5&&num<10) {
f(num-5,n10,n5+1,n1); } else if(num<5&&num>=1) {
f(num-1,n10,n5,n1+1); }
}
注:贪心算法是一种比较简单的算法。贪心算法总是会选择当下的最优解,而不去考虑这一次的选择会不会对未来的选择造成影响。(以寻 找优质解为手段,从而达成整体解决方案的算法)
递归方法如下:
function f(num,n10,n5,n1){ var n10 = n10 || 0, n5 = n5 || 0, n1 = n1 || 0; if(num==0) { console.log("10元:"+n10+"---5元:"+n5+"---1元:"+n1); return; }
贪心算法总是会选择当下的最优解而不去考虑这一次的选择会不会对未来的选择造成影响
贪心算法 ——找零钱问题
//贪心算法 //有三种硬币:10,5,1;给定num元,以最少的硬币数来换它 function greedy(num){ var n10=0, n5=0, n1=0; if(num>=10){ n10= Math.floor(num/10); num= num%10; } if(num>=5){ n5= Math.floor(num/5); num= num%5; } if(num<5){ n1= num; } console.log('10元:'+n10+
贪心:钱币找零问题(C++)

贪⼼:钱币找零问题(C++)贪⼼是⼀种算法范例,它⼀点⼀点地构建解决⽅案,总是选择下⼀个提供最明显和最直接好处的部分。
因此,选择局部最优也会导致全局解的问题最适合贪⼼问题。
例如,考虑分数背包问题。
局部最优策略是选择权重⽐最⼤的项。
这个策略也导致了全局最优解。
假设1元、2元、5元、10元、20元、50元、100元的纸币分别有a,b,c,d,e,f,g张。
现在要⽤这些钱来⽀付m元,⾄少要⽤多少张纸币?⽤贪⼼算法的思想,每⼀次选择最⼤⾯值的钱币。
#include <iostream>#include <vector>#include <algorithm>using namespace std;vector<int> Num{ 3,0,2,1,0,3,5 }, Value{ 1,2,5,10,20,50,100 };int BagsQues(int money) {int sum = 0;for (int i = Value.size() - 1; i >= 0; --i) {int N = min(money / Value[i], Num[i]);money = money - N * Value[i];sum += N;if (money == 0)return sum;}return -1;}int main(){int money;cin >> money;int m = BagsQues(money);cout << m << endl;system("PAUSE");return0;}求出每张⾯额,⽤了多少张:#include <iostream>#include <vector>#include <tuple>#include <algorithm>using namespace std;vector<int> Num{ 3,0,2,1,0,3,5 }, Value{ 1,2,5,10,20,50,100 };vector<tuple<int, int> > BagsQues(int money) {int sum = 0;vector<tuple<int, int> > ch;for (int i = Value.size() - 1; i >= 0; --i) {int N = min(money / Value[i], Num[i]);money = money - N * Value[i];sum += N;if (N != 0) {ch.push_back({ Value[i], N });}if(money == 0)return ch;}ch.clear();ch.push_back({ -1, -1 });return ch;}int main(){int money;cin >> money;vector<tuple<int, int> > m = BagsQues(money);for (int i = 0; i < m.size(); ++i) {cout << get<0>(m[i]) << ":" << get<1>(m[i]) << endl; }system("PAUSE");return0;}。
贪心算法-找零问题 实验报告

实验三课程名称:算法设计与实现实验名称:贪心算法-找零问题实验日期: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. 排队找零问题的难点排队找零问题的难点主要有以下几个方面:(1)每个人所需找零金额不同,且可能存在小数部分。
(2)每个人所持有的纸币种类和数量也不同。
(3)为了确保交易安全性和准确性,每个人必须依次进行交易,并等待收银员完成计算和找零操作。
(4)由于整体交易过程较为繁琐复杂,容易出现错误和漏洞。
3. 排队找零问题的解决方法针对以上难点,在实际应用中可以采用以下几种方法来解决排队找零问题:(1)将所有人的找零金额和所持有的纸币种类和数量进行统计,然后依次进行交易和找零。
(2)采用先进先出的原则,即每个人依次进行交易并找零。
(3)采用计算机算法来优化排队时间和减少等待时间。
三、常见算法1. 贪心算法贪心算法是一种基于贪心思想的算法,它在每一步选择中都采取当前状态下最优的选择,从而希望最终得到全局最优解。
在排队找零问题中,贪心算法可以采用以下策略:(1)尽可能使用面值较小的纸币进行找零。
(2)尽可能避免使用硬币或小面值的纸币。
(3)尽可能让每个人所需找零金额最小化。
贪心算法虽然简单易懂,但是它并不能保证得到全局最优解。
在实际应用中需要注意权衡利弊,并根据具体情况灵活调整策略。
2. 动态规划算法动态规划算法是一种基于分治思想和递归思想的算法,它将原问题分解为若干个子问题,通过求解子问题的最优解来得到原问题的最优解。
在排队找零问题中,动态规划算法可以采用以下策略:(1)将每个人所需找零金额和所持有的纸币种类和数量作为状态变量。
贪婪算法思想及其应用

贪婪算法思想及其应用贪婪算法(Greedy algorithm)是一种常用的算法思想,它根据当前情况做出局部最优的选择,从而希望获得全局最优的解决方案。
贪婪算法通常用于求解优化问题,其特点是简单、高效,并且不需要进行完全的。
贪婪算法的基本思想是通过每一步的局部最优解来建立起全局最优解。
每一步做出的选择依赖于前一步的选择结果,所以贪婪算法通常具有递归的特点。
贪婪算法的目的是使每一步的选择都是最有利的,从而达到整体的最优解。
贪婪算法的应用广泛,下面分别介绍几个常见的应用场景。
1.找零钱问题:假设有一定面值的硬币,要找零钱给客户。
贪婪算法可以选择最大面值的硬币作为找零的一部分,然后继续选择最大面值的硬币,直到完成找零。
这样可以保证找零的硬币数量最少。
2.背包问题:给定一些物品和一个背包,每个物品有一定的重量和价值。
目标是找到一个物品组合,使得其总重量不超过背包容量,但总价值最大。
贪婪算法可以根据每个物品的单位价值(即价值与重量的比值)来选择物品放入背包,以获得最大的总价值。
3.最小生成树问题:给定一个带权无向图,要找到一个包含所有顶点的子图,且该子图的边权重之和最小。
贪婪算法可以从一个顶点开始,每次选择权重最小的边连接到已经选择的顶点集合中的顶点,直到所有顶点都被包含在选择的子图中。
4.哈夫曼编码:哈夫曼编码是一种最优前缀编码方法,用于将字符编码为二进制序列。
贪婪算法可用于构建哈夫曼树,根据字符的出现频率构建最小的二叉树,然后将字符编码为哈夫曼树的路径。
以上只是贪婪算法的一些常见应用,实际上贪婪算法还可以应用于很多其他领域,如任务调度、排序、图着色等。
贪婪算法的优点是简单、高效,但也有一定的局限性,它不能保证一定能得到全局最优解。
因此,在应用贪婪算法时需要根据具体情况来评估其适用性,并结合其他算法和方法来求解问题。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
找零问题贪心算法实现
一、实验描述
当前有面值分别为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 运行结果
四、实验总结
对贪心算法不是特别熟悉,以至于在编写程序时遇到好多错误,好在差不多都改正了,此程序尚有不足之处,希望在以后的深入学习后能编写个更好的程序。