24.贪心算法
贪婪算法(贪心算法)是指在对问题进行求解时,在每一步选择中都采取最好或者最优(即最有利)的选择,从而希望能够导致结果是最好或者最优的算法。
请看下面案例,假设有如下课程,希望尽可能多的将课程安排在一间教室里:
课程 | 开始时间 | 结束时间 |
---|---|---|
美术 | 9:00 | 10:00 |
英语 | 9:30 | 10:30 |
数学 | 10:00 | 11:00 |
计算机 | 10:30 | 11:30 |
音乐 | 11:00 | 12:00 |
这个问题看似要思考很多,实际上算法很简单:
1.选择结束最早的课,便是要在这教室上课的第一节课
2.接下来,选择第一堂课结束后才开始的课,并且结束最早的课,这将是第二节在教室上的课。
重复这样做就能找出答案,这边的选择策略便是结束最早且和上一节课不冲突的课进行排序,因为每次都选择结束最早的,所以留给后面的时间也就越多,自然就能排下越多的课了。
每一节课的选择都是策略内的局部最优解(留给后面的时间最多),所以最终的结果也是近似最优解(这个案例上就是最优解)。
贪婪算法所得到的结果往往不是最优的结果(有时候会是最优解),但是都是相对近似(接近)最优解的结果。
贪婪算法并没有固定的算法解决框架,算法的关键是贪婪策略的选择,根据不同的问题选择不同的策略。
基本思路
其基本的解题思路为:
●建立数学模型来描述问题
●把求解的问题分成若干个子问题
●对每一子问题求解,得到子问题的局部最优解
●把子问题对应的局部最优解合成原来整个问题的一个近似最优解
完整代码:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define N 7
int value[N] = { 1, 2, 5, 10, 20, 50, 100 };
int count[N] = { 10, 2, 3, 1, 2, 3, 5 };
/**************************
*对输入的零钱数,找到至少要用的纸币的数量
*参数:
* money - 要找/支付的零钱数
*返回:
* 至少要用的纸币的数量,-1 表示找不开
*************************/
int solve(int money)
{
int num = 0;
int i = 0;
for (i = N - 1; i >= 0; i--)
{
int j = money / value[i];
int c = j > count[i] ? count[i] : j;
money -= c * value[i];
num += c;
}
if (money > 0) num = -1;
return num;
}
int main()
{
int money = 0;
int num = 0;
printf("请输入要支付的零钱的数额:\n");
scanf_s("%s", &money);
num = solve(money);
if (num == -1)
{
printf("对不起,找不开\n");
}
else
{
printf("成功的使用至少%d 张纸币实现找零/支付!\n", num);
}
system("pause");
return EXIT_SUCCESS;
}
参考资料来源:
奇牛学院