贪心算法的一些模板

贪心

区间选点

给定 N 个闭区间 [a,b],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。输出选择的点的最小数量。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

typedef pair<int, int> PII;

vector<PII> segs;

int main(void) {
    int n;
    scanf("%d", &n);
    
    for (int i = 1; i <= n; ++i) {
        int l, r;
        scanf("%d%d", &l, &r);
        segs.push_back({r, l});
    }
    
    sort(segs.begin(), segs.end());
    
    int res = 0;
    int t = -2e9;
    for (auto it : segs) {
        int l = it.second, r = it.first;
        if (t < l) {
            t = r;
            res++;
        }
    }
    
    cout << res;
    return 0;
    
}

最大不相交区间数量

给定 N 个闭区间 [a,b],请你在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点)。输出可选取区间的最大数量。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

typedef pair<int, int> PII;

vector<PII> segs;

int main(void) {
    int n;
    scanf("%d", &n);
    
    for (int i = 1; i <= n; ++i) {
        int l, r;
        scanf("%d%d", &l, &r);
        segs.push_back({r, l});
    }
    
    sort(segs.begin(), segs.end());
    
    int res = 0;
    int t = -2e9;
    for (auto it : segs) {
        int l = it.second, r = it.first;
        if (t < l) {
            t = r;
            res++;
        }
    }
    
    cout << res;
    return 0;
    
}

区间分组

给定 N 个闭区间 [a,b],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。

输出最小组数。

#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>

#define l first
#define r second

using namespace std;

typedef pair<int, int> PII;

int main(void) {
    int n;
    scanf("%d", &n);
    
    vector<PII> segs;
    
    for (int i = 1; i <= n; ++i) {
        int l ,r;
        scanf("%d%d", &l, &r);
        segs.push_back({l, r});
    }
    
    sort(segs.begin(), segs.end());
    
    priority_queue<int, vector<int>, greater<int>> heap;
    
    for (PII t : segs) {
        if (heap.size() == 0 || heap.top() >= t.l) heap.push(t.r);
        else {
            heap.pop();
            heap.push(t.r);
        }
    }
    
    cout << heap.size();
    return 0;
}

区间覆盖

给定 N 个闭区间 [ai,bi]以及一个线段区间 [s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。

输出最少区间数,如果无法完全覆盖则输出 −1。

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

struct Node {
    int l, r;
    bool operator< (const Node &t) const {
        return l < t.l;
    }
} segs[N];

int main(void) {
    int st, ed;
    scanf("%d%d", &st, &ed);
    int n;
    scanf("%d", &n);
    
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &segs[i].l, &segs[i].r);
    }
    
    sort(segs + 1, segs + n + 1);
    
    int flag = false;
    int res = 0;
    for (int i = 1; i <= n; ++i) {
        int j = i, r = -2e9;
        while (j <= n && segs[j].l <= st) {
            r = max(r, segs[j].r);
            j++;
        }
        
        if (r < st) break;
        
        res++;
        if (r >= ed) {
            flag = true;
            break;
        }
        
        st = r;
        i = j - 1;
    }
    
    if (!flag) res = -1;
    cout << res;
    return 0;
}

Huffman树

#include <iostream>
#include <queue>

using namespace std;

int main(void) {
    priority_queue<int, vector<int>, greater<int>> heap;
    
    int n;
    cin >> n;
    while (n--) {
        int x;
        cin >> x;
        heap.push(x);
    }
    
    int sum  = 0;
    while (heap.size() > 1) {
        int a = heap.top(); heap.pop();
        int b = heap.top(); heap.pop();
        sum += a + b;
        heap.push(a + b);
    }
    
    cout << sum;
    return 0;
    
}
posted @ 2021-07-10 14:22  yangruomao  阅读(132)  评论(0编辑  收藏  举报