贪心算法是指每次取得局部最优解,来达到全局最优解的方法。与动态规划方法类似的是,贪心算法能更大幅度地优化问题的时间复杂度;同样的,对于题目的条件要求也更高,往往要求选手能够有证明贪心算法正确性的把握。

形象地说,动态规划知道不需要搜索什么;而贪心知道需要搜索什么。

很多时候,「题目有贪心解法」是一件可遇不可求的事情,动态规划方法相对来说更加普适。不过,也有一些较为常见的贪心问题。

例题 1:力扣 452. 用最少数量的箭引爆气球

也就是「打气球」问题。

由于力扣使用 C++ 特性较多,提供 ACM 模式参考代码:

参考代码
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef pair<int, int> P;
  4. const int N = 1e5 + 4;
  5. struct Seg {
  6. int l, r;
  7. void read() {
  8. cin >> l >> r;
  9. }
  10. bool operator< (const Seg& rhs) const {
  11. return r < rhs.r;
  12. }
  13. };
  14. Seg a[N];
  15. int n;
  16. int main() {
  17. cin >> n;
  18. for (int i=0; i<n; ++i) {
  19. a[i].read();
  20. }
  21. sort(a, a + n);
  22. int ans = 0;
  23. int ed = -1 << 30;
  24. for (int i=0; i<n; ++i) {
  25. if (a[i].l > ed) {
  26. ++ans;
  27. ed = a[i].r;
  28. }
  29. }
  30. cout << ans << endl;
  31. return 0;
  32. }

例题 2:[NOIP2004]合并果子

做这道题可以回想一下哈夫曼树,哈夫曼编码。具体思路可以理解为先加入的就要一直搬着走,所以先加入最小的。

你需要一个能实时保持元素有序的集合,详见「堆」。

参考代码
#include <bits/stdc++.h>
using namespace std;
priority_queue<int, vector<int>, greater<int>> q;
int n;
int main() {
    cin >> n;
    while (n--) {
        int x;
        cin >> x;
        q.emplace(x);
    }
    int ans = 0;
    while (q.size() > 1) {
        int a = q.top(); q.pop();
        int b = q.top(); q.pop();
        ans += a + b;
        q.emplace(a + b);
    }
    cout << ans << endl;
    return 0;
}

贪心问题比较考验思维,所以,请保持思考。

推荐阅读:贪心