NYOJ 题目12 喷水装置(二) 最小区间覆盖问题

来源:互联网 发布:fenlog软件破解版 编辑:程序博客网 时间:2024/06/12 20:47


先对喷水器进行筛选,把不合格的去掉,然后将喷水器覆盖问题转化为 最小区间覆盖问题,


按照区间左端点从小到大排序,之后进行贪心。



喷水装置(二)

时间限制:3000 ms  |  内存限制:65535 KB
难度:4
描述
有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=10000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。
输入
第一行输入一个正整数N表示共有n次测试数据。
每一组测试数据的第一行有三个整数n,w,h,n表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。
随后的n行,都有两个整数xi和ri,xi表示第i个喷水装置的的横坐标(最左边为0),ri表示该喷水装置能覆盖的圆的半径。
输出
每组测试数据输出一个正整数,表示共需要多少个喷水装置,每个输出单独占一行。
如果不存在一种能够把整个草坪湿润的方案,请输出0。
样例输入
22 8 61 14 52 10 64 56 5
样例输出
12
来源
《算法艺术与信息学竞赛》
上传者
张云聪


#define sqr(x) ((x)*(x))#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>using namespace std;typedef long long ll;const int INF =0x3f3f3f3f;const int maxn=10000    ;int n,m,L,h;double mini;struct Seg{    double le,ri;    Seg(){}    Seg(double le,double ri):le(le),ri(ri){}    bool operator<(const Seg y) const    {        return le<y.le;    }} a[maxn+5];int main(){    int T;    scanf("%d",&T);    double pos,r;    while(T--)    {        scanf("%d%d%d",&m,&L,&h);        mini=  (h/2.0);        n=0;        for(int i=1;i<=m;i++)        {            scanf("%lf%lf",&pos,&r);            if(r<=mini)  continue;            double len=   sqrt( r*r-sqr(h/2.0) );            a[++n]=Seg(pos-len,pos+len);        }        sort(a+1,a+1+n);        double now=0;int i=1,cnt=0 ;         while(now<L)        {            if(i==n+1||a[i].le>now) break;//第一TLE,漏泄后半句判断            double nex=now;            while( i<=n&&a[i].le<=now )            {                nex=max(nex,a[i].ri);                i++;            }            now=nex;            cnt++;        }        if(now<L)  puts("0");        else        {            printf("%d\n",cnt);        }    }   return 0;}


0 0
原创粉丝点击