poj 3614 Sunscreen 贪心

题意:每一头牛有一个接受的防晒霜指数范围,给你每种防晒霜的个数和防晒指数,问最多几头牛能防晒。


网络流解法 :  构图非常简单,源点向每种瓶子连一条瓶子个数的边,瓶子跟能接受的牛连接一条容量为1的边,每头牛向汇点连接一条边容量为1的边,但是这样的话复杂度会比较高,因为点有2500之多。但是比较高效的网络流解法能过。


贪心解法:  先讲牛头按minspf排序,瓶子也排序。然后从防晒指数最小的瓶子开始考虑,能接受他的奶牛当中选择一个maxspf最小的。这样就能得出最优解。

 

简单证明:

        若上述解法没有得出最优解,那么必定存在瓶子i,j。并且i<j。i能满足A牛奶和B奶牛,而j仅能满足A奶牛。并且按前面的操作使得i选择了A奶牛。

         按上述操作可以得出 B.maxspf>A.maxspf  bottle[j].spf<A.maxspf<B.maxspf bottle[j].spf>bottle[i].spf>B.minspf

         那么j能够沐足B奶牛。所以产生了矛盾。

         证毕。


下面是贪心解法的代码。


#include <iostream>

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=2500+9;
int n,l;
struct D
{
    int low,high;
    bool operator < (const struct D &xx) const
    {
        return(low<xx.low);
    }
}d[maxn];
struct B
{
    int spf,sum;
    bool operator < (const struct B &xx) const
    {
        return(spf<xx.spf);
    }
}bottle[maxn];


struct cmp
{
    bool operator() (int a,int b)
    {
        return(a>b);
    }
};


int main()
{
    scanf("%d %d",&n,&l);
    for(int i=1;i<=n;i++)
    scanf("%d %d",&d[i].low,&d[i].high);
    sort(d+1,d+n+1);
    for(int i=1;i<=l;i++)
    scanf("%d %d",&bottle[i].spf,&bottle[i].sum);
    sort(bottle+1,bottle+l+1);


    int ans=0;
    priority_queue <int,vector<int>,cmp> que;
    for(int i=1,k=1;i<=l;i++)
    {
        while(d[k].low<=bottle[i].spf&&k<=n)
        {
            que.push(d[k].high);
            k++;
        }
        for(int j=1;j<=bottle[i].sum;j++)
        {
            while(!que.empty()&&que.top()<bottle[i].spf) que.pop();
            if(!que.empty())
            {
                ans++;
                que.pop();
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

你可能感兴趣的:(poj 3614 Sunscreen 贪心)