算法七:贪婪算法

贪婪算法总是做出在当前看来最好的选择。也就是说,贪婪算法并不从整体最优考虑,它所做出的选择只是局部最优选择。虽然贪婪算法不能对所有问题都得到整体最优解,但对大部分问题它还是能产生整体最优解的。在一些情况下,即使贪婪算法不能得到整体最优解,其最终结果却是最优解的近似解。贪婪算法常以当前情况为基础做最优选择,而不考虑各种可能的整体情况,所以贪婪算法不要回溯。

贪婪算法就是通过做局部最优(贪婪)选择来达到全局最优解。使用贪婪算法时,通常采用自顶向下的方法来求解,每一步都使用最贪婪的选择,使原问题变为一个相似的、规模更小的问题。例如,在下面的例子中所举的找零钱的操作中,每一步都选择当前所能选择的最大面额。

贪婪算法的基本思路:从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快地求得更好的解。当达到算法中的某一步不能再继续前进时,就停止算法,给出近似解。

例如,在超市购物,收银员找零钱时,为使找回零钱的纸币张数(或硬币枚数)最少,不考虑找零钱的所有方案,而是从最大面值的币种开始,按递减的顺序考虑各币种,先尽量用大面值的币种,当不足大面值币种的金额时才去考虑下一种较小面值的币种。这就是使用贪婪法求解的一个典型例子。
例如,要给顾客找回总额为17元的零钱,按贪婪算法,应找1张10元、1张5元、2张1元的即可(不用再考虑其他找零的解法)。

例题一、找零钱

下面编写代码来演示贪婪算法的C程序实现过程。该程序实现超市收银的找零方案,输入需要找补给顾客的金额,由程序计算出该金额可由哪些面额的人民币组成。

【解题思路】人民币有100、50、20、10、5、2、1、0.5、0.2、0.1、0.01等多种面额(单位为元)。在找零钱时,可有多种方案,例如需找零钱68.90元,至少可有以下方案:
  • 1张50、1张10、1张5、3张1、1张0.5、2张0.2;
  • 1张50、1张10、1张5、3张1、1张0.5、4张0.1;
  • 6张10、1张5、3张1、1张0.5、2张0.2

如果按贪婪法来求解,则选中第1种方案,即首先从能找的最大面额开始,找1张50面额的,接着剩下的18.90元又可找1张10元面额的,还剩下8.90元……就这样逐步缩小找钱金额。

详细C代码如下:

#include<stdio.h>

#define MAXN 11
int parvalue[MAXN] = {10000, 5000, 2000, 1000, 500, 200, 100, 50, 20, 10, 1};
int num[MAXN] = {0};

int exchange(int n){
	int i, j;
	for(i = 0; i < MAXN; i++){		/*	找到最大面值	*/ 
		if(n >= parvalue[i])
			break;
	}
	while(n >= 10 && i < MAXN){
		if(n >= parvalue[i]){
			n -= parvalue[i];
			num[i]++;
		}
		else if(n < 10){		//面值为分的情况
			num[MAXN - 1] += n;
			n = 0;
			break;
		}
		else
			i++;
	}
	return 0;
}

int main(){
	int i;
	float m;
	printf("请输入找零金额:");
	scanf("%f", &m);
	exchange((int)100 * m);
	printf("\n%.2f元零钱的组成:\n", m);
	for(i = 0; i < MAXN; i++){
		if(num[i] > 0)
			printf("%6.2f:%d张\n", (float)parvalue[i] / 100.0, num[i]);
	}
	getch();
	return 0;
} 

部分样例结果如下:
在这里插入图片描述

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值