喷水装置(二)
时间限制:
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
来源
- 《算法艺术与信息学竞赛》 上传者
思路 : 其实每个圆都会与草地 有交点。 形成许多的 线段。。。 现在题目要求就是 用最少的线段将这个 区间覆盖完。。
对于无法形成 交点的 圆,他的线段长度就是0 ,,这样就不会影响整个 序列
代码
int i=0; //从第一个线段开始#include<stdio.h> #include<string.h> #include<algorithm> #include<queue> #include<stack> #include<math.h> #include<vector> #define inf 0x3f3f3f #define PI acos(-1); #define LL long long #define M 10000+5 using namespace std; typedef struct { int l,r; }data; data a[M]; int cmp(data a,data b) { if(a.l!=b.l) return a.l<b.l; else return a.r>b.r; } int main() { int t; scanf("%d",&t); while(t--) { int n,w,h; scanf("%d%d%d",&n,&w,&h); for(int i=0;i<n;i++) { int x,r; scanf("%d%d",&x,&r); int temp=(r*r-h*h/4); if(temp<0) a[i].l=a[i].r=0; // 对于这种无法与草地有交点,一定不会用上,用点来表示就不会影响别的数据 else { a[i].l=x-sqrt(temp); if(a[i].l<0) a[i].l=0; a[i].r=x+sqrt(temp); } } sort(a,a+n,cmp); // 按照 起点由小到大排 int sum=0; // 表示现在已经覆盖的 区域长度
int num=0; while(sum<w) { int j=0; for(i;a[i].l<=sum&&i<n;i++) // 每两个线段之间是不能够断的,要不然就不能填满 { j=max(j,a[i].r-sum); // 满足条件下,线段最长的,这样就可以 取的线段最少 } if(j==0) // 说明没有符合条件的,也就是中间一定会断,,就一定不能填满 { num=0; break; } sum+=j; // 不断更新 覆盖区域 num++; // 记录个数 } printf("%d\n",num); } return 0; }
-
第一行输入一个正整数N表示共有n次测试数据。