1. 程式人生 > >POJ3614Sunscreen(優先佇列+貪心)

POJ3614Sunscreen(優先佇列+貪心)

 一共有C個牛,每個牛有一個範圍,在這個範圍內,能夠在陽光下晒,否則被燒烤,同時有L個防晒油,每個防晒油有不同的個數和防晒度,也就是說牛抹了防晒油就有防晒油所定的防晒度了,問一個有多少牛可以不被燒烤

題解中有輸入格式

/*貪心策略:
為了儘可能的讓更多的牛能夠抹上防晒油,那麼我就要儘可能用高於他們忍受範圍下線儘可能接近的防晒油塗他們,所以,用優先佇列排牛的忍受範圍下限從低到高,排列防晒油從低到高,然後從選的那些牛裡面找忍受範圍上限以下的防晒油給他們*/
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 3000;
pair<int, int> c[maxn];
pair<int, int> s[maxn];
priority_queue<int, vector<int>, greater<int> > pq;     //元素越小,越先出隊
int n, m;
int main() {
    /*
    思想:
    先輸入的是奶牛能忍受陽光的最小值及最大值;
    接著是防晒霜能固定的陽光強度及數量;
    先將兩者分別按奶牛所耐陽光最小值及防晒霜所固定值從小到大排序
    列舉每一個防晒霜,遍歷每一個奶牛,看其所耐最小值是否小於等於防晒霜值
    若是,則將其所耐最大值放入佇列(第一個while迴圈實現)接著第二個while迴圈
    判斷佇列內奶牛最大值是否大於等於防晒霜固定值;若是,奶牛數加一,此防晒霜數減1
    */
    while(~scanf("%d%d", &n, &m)) {
        for(int i = 0; i < n; i++)
            scanf("%d%d", &c[i].first, &c[i].second);
            //奶牛的忍受最小最大值
        for(int i = 0; i < m; i++)
            //防晒油的耐值和數量
            scanf("%d%d", &s[i].first, &s[i].second);
        sort(c, c+n);
        sort(s, s+m);//從小到大排序;
        int cur = 0;//奶牛的數量
        int ans = 0;
        for(int i = 0; i < m; i++) {//m瓶
            while(cur < n && c[cur].first <= s[i].first) {
                //防晒霜>=奶牛可忍受最小值
                pq.push(c[cur].second);
                //把其最大值放入優先佇列
                //這個優先佇列自動將裡面的數排好序;
                //把奶牛的耐晒最大值放入佇列;
                cur++;
            }
            while(!pq.empty() && s[i].second) {
                int x = pq.top(); pq.pop();
                //可能未清除完所有牛,留給下一個防晒霜考慮;
                if(s[i].first <= x) {   //當前這種防晒霜的SPF小於等於當前最大的奶牛maxSPF
                    ans++;
                    //如果防晒值小於忍受陽光的最大值;
                    s[i].second--;
                    //可以使用,其數量減1;
                }
                //否則的話,當前這種防晒霜不能無法塗給之前所有的牛
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}