喷水装置(贪心+区间覆盖问题)

n sprinklers are installed in a horizontal strip of grass l meters long and w meters wide. Each sprinkler is installed at the horizontal center line of the strip. For each sprinkler we are given its position as the distance from the left end of the center line and its radius of operation. What is the minimum number of sprinklers to turn on in order to water the entire strip of grass?
在这里插入图片描述
Input
Input consists of a number of cases. The first line for each case contains integer numbers n, l and w with n ≤ 10000. The next n lines contain two integers giving the position of a sprinkler and its radius of operation. (The picture above illustrates the first case from the sample input.)
Output
For each test case output the minimum number of sprinklers needed to water the entire strip of grass. If it is impossible to water the entire strip output ‘-1’.
Sample input

8 20 2
5 3
4 1
1 2
7 2
10 2
13 3
16 2
19 4
3 10 1
3 5
9 3
6 1
3 10 1
5 3
1 1
9 1

Sample Output

6
2
-1

题意 第一行给你数字n 长l 宽w,下面n行分别是洒水装置的位置 和半径 求可以覆盖的最少洒水装置数量

题解 将所有的区间按照左端点从小到大排序,选择覆盖点A的区间中右端点最大的一个,
//并将A更新为这个区间右端点的坐标,再次选择覆盖点A的区间中右端点最大的一个,
//将A更新为这个区间右端点的坐标,如此往复
//如果当前是最大区间 喷头数ans+1;
代码要自己写啊!!!! 写不好就让别人帮你改 好歹知道自己错哪里 不然周测又是一塌糊涂。。。。。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
struct node
{
    double x,y;  //左右区间
} a[15010];
bool cmp(node a,node b)
{
    return a.x<b.x;   //头越小说明 区间越长
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,l,w,flag=1,d=0,i;
        scanf("%d%d%d",&n,&l,&w);
        for (i=1; i<=n; i++)
        {
            int o,r;
            scanf("%d%d",&o,&r);
            if(r>w/2)  //如果喷头半径小于宽度 那么它一块区间都覆盖不了
            {
                a[d].x=o-sqrt(r*r-w*w/4.0);
                a[d].y=o+sqrt(r*r-w*w/4.0);
                d++;     //只有d各喷头满足条件
            }
        }
       // printf("%d\n",d);
        sort(a,a+d,cmp);
        double s,e=0,ans=0;
        i=0;  //当前区间的头,尾,当前到的喷头数,已经用过的喷头数
      //  for(i=0;i<d;i++)
        //   printf("%lf %lf\n",a[i].x,a[i].y);
        while(e<l)
        {
            //printf("***\n");
            s=e;     //当前覆盖的右界
            for(;a[i].x<=s&&i<d;i++)   //当前覆盖的右界在区间内  且喷头没用完
                if(a[i].y>e)      //寻找
                e=a[i].y;

            if(s==e)      //没找到
            {
                flag=0;
                     printf("-1\n");
                break;
            }
            ans++;

        }
        if(flag)
            printf("%.0lf\n",ans);
    }

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值