XYNUOJ 问题 G: 火力覆盖

来源:互联网 发布:gta5捏脸数据吴彦祖 编辑:程序博客网 时间:2024/04/27 19:02

问题 G: 火力覆盖

时间限制: 1 Sec  内存限制: 128 MB
提交: 20  解决: 12
[提交][状态][讨论版]

题目描述

朱日和基地某次演习中,蓝军某火炮部队奉命对某长方形目标区域进行饱和打击。目标区域横向长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

提示

#include<cstdio>#include<cmath>#include<algorithm>using namespace std;struct node{double s;//起点 double e;//终点 }a[10050];bool cmp(node a,node b){if(a.s<b.s)return true;if(a.s==b.s&&a.e>b.e)return true;return false;}int main() { int T,i,j; int n,w,h; int xi,ri,cnt; double wide;  scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&w,&h); int mh=h/2; cnt=0; for(i=0;i<n;i++) { scanf("%d%d",&xi,&ri); if(ri>=mh)//目标打击点的火力覆盖半径小于等于目标区域宽度的一半是没用的  { wide=1.0*sqrt(ri*ri-mh*mh); a[cnt].s=xi-wide;//可以为负数  a[cnt].e=xi+wide;//将实际问题转换成抽象问题,每个目标打击点代表一条线段  //printf("%lf %lf\n",a[cnt].s,a[cnt].e);  cnt++;     }}if(cnt==0){printf("0\n");continue;}sort(a,a+cnt,cmp);         if(a[0].s>0)//最靠前的目标打击点的起始范围大于0,就说明不可能全部覆盖         {printf("0\n");continue;}double max=0,begin=0,end=0;  int ans=0;//完成覆盖共采用多少线段        for(i=0;i<cnt;i++)//cnt 线段个数        {            if(a[i].s<=end)//线段的起点应大于区域的最右点             {                  for(j=i;j<cnt;j++)//选出符合条件而且右端点最远的线段                 {                      if(a[j].e>max&&a[j].e>end&&a[j].s<=end)//核心语句//在剩下的线段中找出所有左端点小于等于当前已经覆盖到的区域的右界限end的线段中,//右端点最大的线段,将其加入,直到覆盖全部的区域。                    {                        max=a[j].e;                    i=j;                    }                }                end=max;//采用,并记录                 max=0;                ans++;             }            if(end>w) //此时当前已覆盖到的区域已经大于区间长度了,完成目标,结束操作 break;        }        if(end<w) //如果遍历处理完所有线段后,仍未能覆盖到区域的右点,说明不能完成覆盖         {            printf("0\n");              continue;          }         printf("%d\n",ans);  } return 0;}




原创粉丝点击