喷水装置(二)

喷水装置(二)

时间限制: 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

这题快折腾死我了,两个小时才AC

思路:

1.将面积转换成区间;

2.按区间左端点排序;

3..根据贪心算法,需要不断更新右端点的值求局部最优解,直到达到要求

PS:喷水装置的半径小于h/2的话,这个装置PASS掉,因为没有用,最优解里当然不会有它;

       两个连续区间若没有交集则无法浸润整个草地;


上源码:

 
 
#include<cstdio>
#include <iostream>
#include<cmath>
#include<algorithm>
using namespace std;
struct device
{
    double left;
    double right;
} a[10001];
bool cmp(device a,device b)
{
    return a.left<b.left;                //排序方式为左端点逆序
}
int main()
{
    int t,n,i,x,r,count,flag;
    double len,sum,max,width,high;
    cin>>t;
    while(t--)
    {
        flag=1;
        sum=0;                            //sum最右边的端点,也可以是覆盖面积
        count=0;
        cin>>n>>width>>high;
        int cnt =0;
        for(i=0;i<n; i++)
        {
            cin>>x>>r;
            if(r<=high/2)                //判断该喷水装置是否有用
                continue;
            len=sqrt(1.0*r*r-1.0*high/2*high/2);    //计算区间半径,不会就拿纸推一推
            a[cnt].left=x-len;           //该装置的左端点
            a[cnt].right=x+len;          //该装置的右端点
            cnt++;                       //有用的装置+1
        }
        sort(a,a+cnt,cmp);
        while(sum<width)                 //直到草地全部浸润退出
        {
            max=0;
            for(i=0; i<cnt&&a[i].left<=sum; i++) //左端点不能大于最右的端点
                if((a[i].right-sum)>max)         //找向右延伸的最大值
                    max=a[i].right-sum;
            if(max==0)                           //如果上一个就是最右的端点到且sum<width,则区间不能完全覆盖,标志后退出即可
            {
                flag=0;
                break;
            }
            else
            {
                sum+=max;                        //更新右端点
                count++;                         //该装置有用
            }
        }
        if(flag==1)
            cout<<count<<endl;
        else
            cout<<"0"<<endl;
    }
    return 0;
}
//每天进步一些



猜你喜欢

转载自blog.csdn.net/wen2471145970/article/details/80559136