数据结构与算法 贪心算法介绍和举例

贪心算法是一种常用的算法思想,它通过每次选择局部最优解的方式来构造全局最优解。下面以一个经典的问题“找零钱”为例来说明贪心算法的应用。

假设现在有一些硬币,它们的面值分别为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个会议。