贪心算法
贪婪算法(贪心算法)是指在对问题进行求解时,在每一步选择中都采取最好或者最优(即最有 利)的选择,从而希望能够导致结果是最好或者最优的算法。
请看下面案例
假设有如下课程,希望尽可能多的将课程安排在一间教室里:
这个问题看似要思考很多,实际上算法很简单:
-
选择结束最早的课,便是要在这教室上课的第一节课
-
接下来,选择第一堂课结束后才开始的课,并且结束最早的课,这将是第二节在教室上的 课。
重复这样做就能找出答案,这边的选择策略便是结束最早且和上一节课不冲突的课进行排序, 因为每次都选择结束最早的,所以留给后面的时间也就越多,自然就能排下越多的课了。
每一节课的选择都是策略内的局部最优解(留给后面的时间最多),所以最终的结果也是近似最 优解(这个案例上就是最优解)。
贪婪算法所得到的结果往往不是最优的结果(有时候会是最优解),但是都是相对近似(接近)最 优解的结果。
贪婪算法并没有固定的算法解决框架,算法的关键是贪婪策略的选择,根据不同的问题选择 不同的策略。
基本思路
其基本的解题思路为:
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日, (由于疫情的原因), 家里的很多弟弟现在才会学校, 只有两位姐姐和我老表. 写博客,也可自己加强记忆,就当写写日记吧!!!
希望给个赞: 反正你又不亏, 顺便而已