贪心算法 找零钱问题

合集下载

第三章贪心方法(GreedyTechnique)

第三章贪心方法(GreedyTechnique)
其次考虑物品2。就Δ M=10而言有,也只能选择物品2 的一部分装入背包。下一步将放入物品2的10/15装包, 即
x2=10/15=2/3 最后,背包装满Δ M=0,物品1将不能装入背包,故 x1=0 。
背包最终可以获得效益值= x1 p1 +x2 p2+x3 p3 = 31 (次优解,非问题的最
3)最优的度量标准
① (1/2,1/3,1/4) ② (1, 2/15, 0 ) ③ (0, 2/3, 1) ④ (0, 1, 1/2)
16w.5i xi
20 20 20
效益
pi xi
24.25 28.2 31 31.5
//没有装满背包//
2. 贪心策略求解
度量标准的选择:三种不同的度量标准选择
1)以目标函数作为度量 即,每装入一件物品,就使背包获得最大可能的效益
引例2 铺砖问题
有若干种不同规格的砖,要铺满一块平台, 希望用较少的砖达到目的。
例如,有三种规格的砖:2*2,0.8*0.8, 0.1*0.1,要铺满2.5*2.5的平面。
采用贪心策略:首先是最大规格的砖2*2 一块,再考虑次大的0.8*0.8,无法放入, 再考虑最小的0.1*0.1,要25*5+20*5=225块
10 1
2 50
45
40 35 3
30
5
25 55
4
15
20 6
边 (1,2) (2,6)
成本 10 25
(3,6) 15
1
2
1
2
6
1
2
3
6
(6,4) 20
1
234 6源自边 (3,5)成本 35
10
1
2

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

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

证明人民币找零问题贪心算法的正确性问题提出:根据人们生活常识,我们到商店里买东西需要找零钱时,收银员总是先给我们最大面值的,要是不够再找面值小一点的,直到找完为止。

这就是一个典型的贪心选择问题。

问题描述:当前有面值分别为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)均应为最大数量了,所以贪心算法得到的解是最优解,即满足贪心选择性质。

经典贪心题

经典贪心题

贪心算法是一种在解决问题的过程中追求局部最优的算法,对于一个有多种属性的事物来说,贪心算法会优先满足某种条件,追求局部最优的同时希望达到整体最优的效果。

以下是一些经典的贪心算法问题:1. 背包问题:给定一组物品,每个物品都有自己的重量和价值,背包的总容量有限。

贪心算法需要选择物品以最大化背包中物品的总价值,同时不超过背包的总容量。

这种问题可以有多种变体,例如分数背包问题和完全背包问题。

2. 硬币找零问题:给定一组硬币的面值和数量,以及需要找零的金额。

贪心算法需要选择硬币以最小化找零的总数量。

这个问题可以通过从大到小排序硬币,并从最大面值的硬币开始选择,直到找零的金额达到所需的总金额。

3. 区间选点问题:给定一系列闭区间,每个闭区间都有一个起始点和结束点。

贪心算法需要选择尽量少的点,使得每个闭区间内至少有一个点被选中。

这个问题可以通过对结束点进行排序,并从左到右选择结束点,直到下一个要选择的结束点与上一个选择的结束点之间的距离大于当前选择的结束点与上一个选择的结束点之间的距离为止。

4. 区间覆盖问题:给定一系列闭区间,贪心算法需要选择尽量少的区间,使得所有区间都被覆盖。

这个问题可以通过对每个闭区间的左端点进行排序,并从左到右选择左端点,直到下一个要选择的左端点与上一个选择的左端点之间的距离大于当前选择的左端点与上一个选择的左端点之间的距离为止。

5. 排班问题:给定一组员工和他们的班次需求,以及一组工作日的日程安排。

贪心算法需要为员工分配班次,以最小化总工作时间并满足所有工作日的需求。

这个问题可以通过从可用的班次中选择最长的班次,并从左到右分配员工,直到所有员工都被分配到一个班次为止。

这些问题是贪心算法的经典示例,它们展示了贪心算法在解决优化问题中的广泛应用。

贪心算法 实验报告

贪心算法 实验报告

贪心算法实验报告贪心算法实验报告引言:贪心算法是一种常用的算法设计策略,它通常用于求解最优化问题。

贪心算法的核心思想是在每一步选择中都选择当前最优的解,从而希望最终能够得到全局最优解。

本实验旨在通过实际案例的研究,探索贪心算法的应用和效果。

一、贪心算法的基本原理贪心算法的基本原理是每一步都选择当前最优解,而不考虑整体的最优解。

这种贪婪的选择策略通常是基于局部最优性的假设,即当前的选择对于后续步骤的选择没有影响。

贪心算法的优点是简单高效,但也存在一定的局限性。

二、实验案例:零钱兑换问题在本实验中,我们以零钱兑换问题为例,来说明贪心算法的应用。

问题描述:假设有不同面值的硬币,如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个。

贪心算法几个经典例子c语言

贪心算法几个经典例子c语言

贪心算法几个经典例子c语言1. 零钱兑换问题题目描述:给定一些面额不同的硬币和一个总金额,编写一个函数来计算可以凑成总金额所需的最少的硬币个数。

如果没有任何一种硬币组合能够凑出总金额,返回 -1。

贪心策略:每次选择面额最大的硬币,直到凑出总金额或者无法再选择硬币为止。

C语言代码:int coinChange(int* coins, int coinsSize, int amount){int count = 0;for(int i = coinsSize - 1; i >= 0; i--){while(amount >= coins[i]){amount -= coins[i];count++;}}return amount == 0 ? count : -1;}2. 活动选择问题题目描述:有 n 个活动,每个活动都有一个开始时间和结束时间,选择一些活动使得它们不冲突,且能够参加的活动数最多。

贪心策略:每次选择结束时间最早的活动,直到所有活动都被选择或者无法再选择为止。

C语言代码:typedef struct{int start;int end;}Activity;int cmp(const void* a, const void* b){return ((Activity*)a)->end - ((Activity*)b)->end;}int maxActivities(Activity* activities, int n){qsort(activities, n, sizeof(Activity), cmp);int count = 1;int end = activities[0].end;for(int i = 1; i < n; i++){if(activities[i].start >= end){count++;end = activities[i].end;}}return count;}3. 跳跃游戏题目描述:给定一个非负整数数组,你最初位于数组的第一个位置。

因为贪心而失败的例子

因为贪心而失败的例子

因为贪心而失败的例子贪心算法是一种常用的解决问题的算法思想,它通常在每一步选择中都采取当前状态下最好或最优的选择,从而希望最终能够达到全局最优的结果。

然而,贪心算法的贪心选择可能会导致最终结果并非全局最优,而是局部最优或者根本无法得到可行解。

因此,贪心算法在某些问题上会因为贪心而失败。

下面将列举10个因为贪心而失败的例子。

1. 颜色分配问题:假设有n个节点需要着色,并且相邻的节点不能具有相同的颜色。

贪心算法选择每次都选择可用颜色最少的节点进行着色。

然而,这种贪心选择可能会导致最终无法着色所有节点,因为后续节点的颜色选择受到前面节点的限制。

2. 找零问题:假设需要找零的金额为m,而只有面额为1元、5元、10元的硬币。

贪心算法选择每次都选择面额最大的硬币进行找零。

然而,在某些情况下,贪心选择可能会导致找零的硬币数量不是最小的。

3. 最小生成树问题:在一个连通图中,选择一些边构成一个树,使得这些边的权值之和最小,同时保证图中的所有节点都能够通过这些边连通。

贪心算法选择每次都选择权值最小的边加入到树中。

然而,这种贪心选择可能会导致最终得到的树不是最小生成树。

4. 背包问题:给定一组物品,每个物品有自己的重量和价值,在给定的背包容量下,选择一些物品放入背包中,使得背包中物品的总价值最大。

贪心算法选择每次都选择单位重量价值最大的物品放入背包中。

然而,在某些情况下,贪心选择可能会导致最终得到的背包价值不是最大的。

5. 最短路径问题:在一个有向图中,找到两个节点之间的最短路径。

贪心算法选择每次都选择距离最近的节点进行扩展。

然而,这种贪心选择可能会导致最终得到的路径不是最短的。

6. 任务调度问题:给定一组任务,每个任务有自己的开始时间和结束时间,在给定的时间段内,选择一些任务进行调度,使得能够完成尽可能多的任务。

贪心算法选择每次都选择结束时间最早的任务进行调度。

然而,在某些情况下,贪心选择可能会导致最终完成的任务数量不是最多的。

贪心:钱币找零问题(C++)

贪心:钱币找零问题(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. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

学号
《算法设计与分析》
实验报告三
学生姓名
专业、班级
指导教师
成绩
电子与信息工程系
实验三:贪心算法运用练习
一、实验目的
本次实验是针对贪心算法运用的算法设计及应用练习,旨在加深学生对该部分知识点的理解,提高学生运用该部分知识解决问题的能力。

二、实验步骤与要求
1.实验前复习课程所学知识以及阅读和理解指定的课外阅读材料;
2.学生独自完成实验指定内容;
3.实验结束后,用统一的实验报告模板编写实验报告。

4.提交说明:
(1)电子版提交说明:
a 需要提交Winrar压缩包,文件名为“《算法设计与分析》实验二_学号_姓名”,
如“《算法设计与分析》实验二_09290101_张三”。

b 压缩包内为一个“《算法设计与分析》实验二_学号_姓名”命名的顶层文件夹,
其下为两个文件夹,一个文件夹命名为“源程序”,另一个文件夹命名为“实验
报告电子版”。

其下分别放置对应实验成果物。

(2)打印版提交说明:
a 不可随意更改模板样式。

b 字体:中文为宋体,大小为10号字,英文为Time New Roman,大小为10号
字。

c 行间距:单倍行距。

(3)提交截止时间:2012年12月7日16:00。

三、实验项目
1.传统的找零钱问题的算法及程序实现。

2.特殊的0-1背包问题的求解:本次求解的0-1背包问题的特点为每种物品各有M件,已知每个物品的单位价值,求使得所获价值最大的装包方案。

四、实验过程
找零钱问题:
#include<iostream>
using namespace std;
void Zl(double num)
{
int leave=0;
int a[8];
leave = (int)(num*10)%10;
a[1] = leave/5;
a[0] = (leave%5)/1;
a[7] = num/50;
a[6] = ((int)num%50)/20;
a[5] = (((int)num%50)%20)/10;
a[4] = ((((int)num%50)%20)%10)/5;
a[3] = (((((int)num%50)%20)%10)%5)/2;
a[2] = ((((((int)num%50)%20)%10)%5)%2)/1;
if(a[0]!=0)
cout<<"需要找的0.1元个数为:"<<a[0]<<endl;
if(a[1]!=0)
cout<<"需要找的0.5元个数为:"<<a[1]<<endl;
if(a[2]!=0)
cout<<"需要找的1元个数为:"<<a[2]<<endl;
if(a[3]!=0)
cout<<"需要找的2元个数为:"<<a[3]<<endl;
if(a[4]!=0)
cout<<"需要找的5元个数为:"<<a[4]<<endl;
if(a[5]!=0)
cout<<"需要找的10元个数为:"<<a[5]<<endl;
if(a[6]!=0)
cout<<"需要找的20元个数为:"<<a[6]<<endl;
if(a[7]!=0)
cout<<"需要找的50元个数为:"<<a[7]<<endl;
}
void main ()
{
double num;
// int
cout<<"请输入你需要找的零钱数:"<<endl;
cin>>num;
Zl(num);
cout<<endl;
return;
}
五、实验总结。

相关文档
最新文档