贪心算法是一种常用的算法思想,它通过每次选择局部最优解的方式来构造全局最优解。下面以一个经典的问题“找零钱”为例来说明贪心算法的应用。
假设现在有一些硬币,它们的面值分别为1元、5元、10元、50元、100元、500元,现在需要找回n元的零钱,如何选择硬币数量最少的方案?
一种贪心策略是每次选择当前能找零的最大面额的硬币。例如,当需要找回27元的零钱时,首先选择一个面额为10元的硬币,剩余17元,然后选择一个面额为10元的硬币,剩余7元,接着选择一个面额为5元的硬币,剩余2元,最后选择两个面额为1元的硬币即可。
虽然这种贪心策略不能保证一定得到最优解,但是对于这个问题,它可以得到最优解。这是因为硬币的面额是一些特殊的值,它们的倍数关系使得每次选择最大面额的硬币可以得到最优解。
当然,对于不同的问题,贪心策略可能不同,也可能存在不能得到最优解的情况。因此,在使用贪心算法时,需要对问题进行分析,确定贪心策略的正确性。
下面以一个具体的问题为例来演示贪心算法的实现。
问题描述:假设有n个会议要在同一天举行,每个会议有开始时间和结束时间,不同会议之间时间可以重叠。如何安排这些会议的时间,使得参加的会议数量最多?
解决思路:贪心算法可以通过每次选择结束时间最早的会议来进行安排,因为这样可以给后面的会议留出更多的时间空间,从而能够安排更多的会议。
代码实现:
#include <iostream>
#include <algorithm>
using namespace std;
struct Meeting {
int start, end;
};
bool cmp(Meeting a, Meeting b) { //按照结束时间从小到大排序
return a.end < b.end;
}
int main() {
int n; //会议数量
cin >> n;
Meeting meetings[n];
for (int i = 0; i < n; i++) {
cin >> meetings[i].start >> meetings[i].end;
}
sort(meetings, meetings + n, cmp); //按照结束时间从小到大排序
int cnt = 1; //至少有一个会议可以参加
int cur_end = meetings[0].end; //当前安排的会议结束时间
for (int i = 1; i < n; i++) {
if (meetings[i].start >= cur_end) { //如果下一个会议的开始时间晚于等于当前安排的会议的结束时间,则可以参加该会议
cnt++;
cur_end = meetings[i].end; //更新当前安排的会议的结束时间
}
}
cout << cnt << endl; //输出最多可以参加的会议数量
return 0;
}
例如,当输入以下数据时:
5
1 3
2 4
3 5
4 6
5 7
程序输出结果为:
2
说明最多可以参加2个会议,一种可行的安排方案是选择第1个会议和第5个会议。