C/C++_五大常规算法_贪心算法

贪心算法

贪婪算法(贪心算法)是指在对问题进行求解时,在每一步选择中都采取最好或者最优(即最有 利)的选择,从而希望能够导致结果是最好或者最优的算法。

请看下面案例
假设有如下课程,希望尽可能多的将课程安排在一间教室里:
在这里插入图片描述
这个问题看似要思考很多,实际上算法很简单:

  1. 选择结束最早的课,便是要在这教室上课的第一节课

  2. 接下来,选择第一堂课结束后才开始的课,并且结束最早的课,这将是第二节在教室上的 课。

重复这样做就能找出答案,这边的选择策略便是结束最早且和上一节课不冲突的课进行排序, 因为每次都选择结束最早的,所以留给后面的时间也就越多,自然就能排下越多的课了。

每一节课的选择都是策略内的局部最优解(留给后面的时间最多),所以最终的结果也是近似最 优解(这个案例上就是最优解)。

贪婪算法所得到的结果往往不是最优的结果(有时候会是最优解),但是都是相对近似(接近)最 优解的结果。

贪婪算法并没有固定的算法解决框架,算法的关键是贪婪策略的选择,根据不同的问题选择 不同的策略。

基本思路

其基本的解题思路为:

1、建立数学模型来描述问题
2、把求解的问题分成若干个子问题
3、对每一子问题求解,得到子问题的局部最优解
4、把子问题对应的局部最优解合成原来整个问题的一个近似最优解

在这里插入图片描述
参考:

/* 贪心算法 */
#include <stdio.h>
#include <stdlib.h>

#define N 7

int value[N] = { 1,2,5,10,20,50,100 }; /* 钱的种类 */
int count[N] = { 10,10,10,10,10,10,10 }; /* 不同钱的种类_张数*/

/***************************************
* 对于输入的零钱, 找到至少要用的纸币的数量
* 参数:
*	money - 要找/支付的零钱数
* 返回:
*	至少要用的纸币的数量, -1 表示找不开
***************************************/
int solve(int money)
{
	int num = 0;
	int i = 0;


	for (i = N - 1; i >= 0; i--)
	{
		int j = money / value[i]; //210/100=2 120/100=1
		int c = j > count[i] ? count[i] : j; // 需要的张数>现有的张数?现有的张数:需要的张数

		printf("需要用面值 %d 的纸币 %d 张\n", value[i], c);

		money = money - c * value[i]; 
		num = num + c; /* 张数的累加 */

		if (money == 0) break; /* 直到找零结束跳出循环 */

	}

	if (money > 0)
	{
		num = -1;
	}

	return num;
}

int main()
{
	int money = 0;
	int num = 0;

	printf("请输入要支付的零的数目: \n");
	scanf_s("%d", &money);

	num = solve(money);

	if (num == -1)
	{
		printf("对不起,找不开\n");
	}
	else
	{
		printf("成功的使用至少%d 张纸币实现找零/支付! \n", num);
	}

	system("pause");
	return 0;
}

运行环境: vs2019
运行结果:
在这里插入图片描述

结语:

学到的知识要, 多复习, 多总结, 多敲. 需要时间的积累, 才能引起质的改变. 自己写不出来的永远是别人的.

分享一下我的技巧: 代数法把具体的数字带进去, 看看能能能找到规律(掌握思想).
还有就是画图, 也很重要. 用笔画出来, 把数代进去, 方法虽然笨, 但真的很实用, 好记忆不如烂笔头!!!

我是小白, C/C++功力…, 你懂得, 写的文章可能不是很好. 如果存在问题, 欢迎大神给予评判指正.
错了不可怕, 可怕的是找不出bug, 谁没错过!!!

最近学操作系统我认为, 学什么都要成本(时间), 即使它是免费的, 我个人认为要挑来学, 挑重点来学, 而不是从头到尾, 除非考试考研.

今日是: 2020年5月11日, (由于疫情的原因), 家里的很多弟弟现在才会学校, 只有两位姐姐和我老表. 写博客,也可自己加强记忆,就当写写日记吧!!!

希望给个赞: 反正你又不亏, 顺便而已

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值