Sunscreen (poj 3614 贪心+优先队列)zai

本文介绍了一道关于防晒霜分配的问题,通过贪心算法解决如何最优地为每头牛选择合适的防晒霜,使得尽可能多的牛能在阳光下舒适地晒太阳。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:有c头牛晒太阳,每头牛都有一个能承受辐射的范围(min~max),现在有 l 种防晒霜,每种防晒霜都能将辐射值固定在spf,每种防晒霜都有一定的数量num。每头牛用最多一种防晒霜,问能满足多少斗牛。

思路:贪心,首先防晒霜按照spf从小到大排序,牛也按照能承受的最小值从小到大排序。然后对于每种防晒霜 将牛的最小值 小于等于 该种防晒霜spf值的牛入队列(只如它承受范围的最大值),然后较小者先出队列。

http://poj.org/searchproblem?field=source&key=USACO+2007+November+Gold

对于这个题 我一开始没思路 很苦恼啊

后来我想了xiang  思路大概是这样的微笑吐舌头

奶牛有自己的范围,弄个结构体装begin end

这个范围排序 

int cmp(Cow  a,Cow b)
{
    return a.begin<b.begin;
}

在说防晒霜 

struct Sunscreen
{
    int p;
    int  num;

}s[maxn];
int cmp2(Sunscreen a,Sunscreen b)
{
    return a.p<b.p;
}

也可以

int cmp2(const Sunscreen& a,const Sunscreen& b)
{
    return a.p<b.p;
}


我们以方晒霜为基准拍一下

   第一个防晒霜        最小阈值<fang晒霜 同时奶牛存在 奶牛的最大阈值进栈 同时去排下一个奶牛

    while(i<c&& cow[i].begin<s[j].p)
            {
                    Q.push(cow[i].end);
                    i++;
            }



对拍完了 此时队列里面是最小值小于防晒霜得最大值

判断奶牛最大值和防晒霜的大小

 while(!Q.empty() && s[j].num)
            {
                m=Q.top();
                Q.pop();
                if(s[j].p<m)
                {
                    n++;
                    s[j].num--;
                }
            }
如果符合 符合情况奶牛++ 该类型的防晒霜--

再去排第二类防晒霜 此时i并没有清零 而是继续i++


关于防晒霜排序的一些看法

1

若果 i的最大值小于防晒霜则个就直接略了 因为后面之后比最大值更大

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=100;
int c,l;
struct Cow{
    int begin;
    int end;

}cow[maxn];
struct Sunscreen
{
    int p;
    int  num;

}s[maxn];

int cmp(Cow  a,Cow b)
{
    return a.begin<b.begin;
}
int cmp2(const Sunscreen& a,const Sunscreen& b)
{
    return a.p<b.p;
}
priority_queue<int ,vector<int>,greater<int> > Q;
int main()
{
    int m,n;
    while(scanf("%d%d",&c,&l)==2)
    {
        for(int i=0;i<c;i++)
        {
            scanf("%d%d",&cow[i].begin,&cow[i].end);
        }
        for(int j=0;j<l;j++)
        {
            scanf("%d%d",&s[j].p,&s[j].num);

        }
        sort(cow,cow+c,cmp);
        sort(s,s+l,cmp2);
        int  i=0;

        for(int j=0;j<l;j++)
        {
            while(i<c&& cow[i].begin<s[j].p)
            {
                    Q.push(cow[i].end);
                    i++;
            }
            while(!Q.empty() && s[j].num)
            {
                m=Q.top();
                Q.pop();
                if(s[j].p<m)
                {
                    n++;
                    s[j].num--;
                }
            }
        }
        printf("%d",n);
    }
    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值