POJ3614这个题很坑,我也是无语,但也怪自己吧

此题大意:
有一些奶牛,它们想晒黑皮肤,每只奶牛有一个min_SPA 和 max_SPA,如果高于max_SPA,就不能晒黑,低于的话就会晒伤,而题上又给了几瓶防晒霜,能够使奶牛达到一定SPA,并且一瓶可以几头奶牛一起用,让你求最大的晒黑的奶牛头数。

开始我是这样理解的:
先对奶牛的SPA进行排降序,以max为主,min为辅;
然后对防晒霜排降序,以SPA的值为主,防晒头数为辅;
然后循环找防晒霜覆盖的范围;

但事实上我漏了一点就是下面这种情况:
3 2
1 6
3 4
3 4
3 1
2 1
从图上可以看出,如果找的第一个是最大的1 6,那么接下来就找不到其它的了,事实上却是可以的

因此,我改进了一下:
在找的时候运用了堆维护找到的大于防晒霜SPA的max的min,换句话说就是维护min_SPA;
于是就解决了这个问题。

代码如下:

#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>

#define maxn 3000

using namespace std;

struct node
{
    int x,y;
};

node C[maxn], L[maxn];

bool cmp1(node num1, node num2)
{
    if (num1.y == num2.y) return num1.x > num2.x;
    else return num1.y > num2.y;
}

bool cmp2(node num1, node num2)
{
    if (num1.x == num2.x) return num1.y > num2.y;
    else return num1.x > num2.x;
}

int main()
{
    priority_queue<int, vector<int> > que; // 大顶堆
    int c, l;
    scanf("%d%d", &c, &l);
    for (int i = 0; i < c; ++i)
        scanf("%d%d", &C[i].x, &C[i].y);   //以y为主,x为辅排序
    for (int i = 0; i < l; ++i)
        scanf("%d%d", &L[i].x, &L[i].y);   //以x为主,y为辅排序
    sort(C, C + c, cmp1);
    sort(L, L + l, cmp2);

    int ans = 0, j = 0;
    for (int i = 0; i < l; ++i)
    {
        while (j < c && C[j].y >= L[i].x)  //将大于乳液的光照强度的奶牛的min_FPA放进堆里维护
        {
            que.push(C[j].x);
            ++j;
        }

        while (!que.empty() && L[i].y)     //将维护的数据从小开始取
        {
            int num = que.top();
            que.pop();
            if (L[i].x < num) continue;    //若大于了乳液的光照强度,则不能使用
            ++ans;
            --L[i].y;
        }
    }
    printf("%d\n", ans);

    return 0;
}

你可能感兴趣的:(堆,poj,贪心)