贪心—Ⅰ

  • 防晒

原题链接

我们首先将奶牛可以承受的最小值,递减排序,也就是降序排列,然后将防晒霜固定的值,递减排序,还是降序排列.

对于每头奶牛,扫描一遍所有防晒霜,在这头奶牛能用的防晒霜里找SPF最大的使用

注意:降序排序,保证对于每一头牛而言,它用的是,可以使用的最差的防晒霜,因为值越小的防晒霜,有可能让更多的牛使用.而升序排列,就恰好反了.

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>

using namespace std;

const int N=3500;
int n,m;

struct node
{
    int spf,cover;
}a[N];

struct node2
{
    int min_spf,max_spf;
}b[N];

bool cmp1(node2 a,node2 b)
{
        return a.min_spf>b.min_spf;
}

bool cmp2(node a,node b)
{
        return a.spf>b.spf;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
        scanf("%d%d",&b[i].min_spf,&b[i].max_spf);
    sort(b,b+n,cmp1);
    for(int i=0;i<m;i++)
        scanf("%d%d",&a[i].spf,&a[i].cover);
    sort(a,a+m,cmp2);
    
    int ans=0;
    for(int i=0;i<n;i++)//枚举奶牛
    {
        for(int j=0;j<m;j++)//枚举防晒霜
        {
            if(a[j].spf>=b[i].min_spf&&a[j].spf<=b[i].max_spf&&a[j].cover)
            {
                ans++;
                a[j].cover--;
                break;//枚举下一头奶牛
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}
  • 畜栏预定

原题链接

贪心+小根堆

维护一个小根堆,记录当前每个畜栏安排进去的最后一头牛
依次对于每头牛,与小根堆堆顶比较,若不小于畜栏最后一头牛结束吃草的时间,则加入,如果这样的畜栏不存在,则为其新建一个畜栏

时间复杂度为:O(NlogN)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>

using namespace std;

typedef pair<int,int>PII;

const int N=50010;

int n;

int id[N];//牛对应其牛栏号
pair<PII,int>cow[N];



int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        cow[i]={{l,r},i};//第i号牛的进与出
    }
    
    sort(cow,cow+n);//按照左端点排序,一个一个加
    
    priority_queue<PII,vector<PII>,greater<PII> >heap;
    int num=1;
    
    heap.push({cow[0].first.second,num});//0号牛最晚结束时间,即其牛栏号
    
    id[cow[0].second]=1;//0号牛对应栅栏1号
    
    //往里面放牛
    for(int i=1;i<n;i++)
    {
         int l=cow[i].first.first,r=cow[i].first.second,cowid=cow[i].second;
         
         if(l>heap.top().first)//若这只牛能放进这里面
         {
             int t=heap.top().second;//记录一下牛栏号
             heap.pop();//此牛栏更新最晚结束时间
             heap.push({r,t});
             id[cowid]=t;
         }
         else//新建牛栏
         {
             heap.push({r,++num});
             id[cowid]=num;
         }
    }
    cout<<heap.size()<<endl;
    for(int i=0;i<n;i++)
        cout<<id[i]<<endl;
    
    return 0;
}
  • 雷达设备

原题链接

由勾股定理可知,将所有小岛转化成区间后,问题转化为:给定 n 个区间,在 x 轴上选择尽量少的点,使得所有区间至少包含一个点。

算法步骤:

将所有区间按右端点从小到大排序;

依次考虑每个区间:如果当前区间包含最后一个选择的点,则直接跳过;如果当前区间不包含最后一个选择的点,则在当前区间的右端点的位置选一个新的点;

时间复杂度:

计算每个坐标所对应的区间,需要 O(n) 的计算量;
将所有区间排序需要 O(nlogn) 的计算量;
扫描所有区间需要 O(n) 的计算量;
所以总共的时间复杂度是 O(nlogn)。

#include<iostream>
#include<algorithm>
#include<cmath>

using namespace std;

const int N=1005;

typedef pair<double,double>PDD;

double INF=0x3f3f3f3f;
int n,r;

PDD seg[N];

int main()
{
    cin>>n>>r;
    
    bool success=true;
    
    for(int i=0;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if(y>r)
        {
            success=false;
            break;
        }
        auto len=sqrt(r*r-y*y);
        seg[i]={x+len,x-len};
    }
    if(!success)
    {
        printf("-1\n");
    }
    else
    {
        sort(seg,seg+n);//按照尾边排序
        int res=0;//统计雷达数
        double last=-INF;
        for(int i=0;i<n;i++)
        {
            if(seg[i].second>last)
            {
                res++;
                last=seg[i].first;
            }
        }
        cout<<res;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值