南阳oj 12 喷水装置(二)

来源:互联网 发布:怎么删除淘宝订单记录 编辑:程序博客网 时间:2024/05/17 12:23

喷水装置(二)
时间限制: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。
样例输入
2
2 8 6
1 1
4 5
2 10 6
4 5
6 5
样例输出
1
2
这道题其实就是区间覆盖问题,数轴上有 n 个闭区间 [a, b],选取尽量少的区间覆盖题中给出的[0,w];
用 sum 记录当前在线段上覆盖到的位置,每次对整个闭区间扫描,
扫描结果:
1. 线段上有的区间覆盖不到,则无法完成覆盖,跳出扫描循环;
2. 选择能覆盖到 sum 位置且最长的闭区间,用它来覆盖,贪心,保证选的区间少,sum += mlen。
3. mlen为使用当前装置能够覆盖的最大长度
注意:结构体里面的左右点是double类型的,因为有根号的运算;
代码如下:

#include<stdio.h>#include<cstring>#include<iostream>#include<algorithm>#include<math.h>#include<stdlib.h>#include<stack>#include<vector>#include<string.h>#include<map>#define INF 0x3f3f3f3f3fusing namespace std;int x[10005],r[10005];struct node{    double a;    double b;} q[10005];double cmp(node aa,node bb){    return aa.a==bb.a?aa.b<bb.b:aa.a<bb.a;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,w,h;        scanf("%d%d%d",&n,&w,&h);        int k=0;        for(int i=0; i<n; i++)        {            int xi,ri;            scanf("%d%d",&xi,&ri);            if(2*ri>h)     //如果半径小于h/2的话,证明这个装置无法使用            {                double jv=sqrt((double)ri*ri-(double)h*h/4.0);                q[k].a=(double)xi-jv;                 // 区间的左端点                q[k].b=(double)xi+jv;                 // 区间的右端点                k++;            }        }        if(k==0)        {            printf("0\n");                         // 没有符合的装置            break;        }        else        {            sort(q,q+k,cmp);            double sum=0;            int ans=0;            while(sum<w)            {                double mlen=0;       //选择当前装置能覆盖的最大长度                for(int i=0; i<k; i++)                {                    if(q[i].a<=sum&&mlen<q[i].b-sum)             //选择合适的而且最优的                    {                        mlen=q[i].b-sum;                    }                }                if(mlen==0)                {                    ans=0;                    break;                }                sum+=mlen;                ans++;            }            printf("%d\n",ans);        }    }}
1 0
原创粉丝点击