问题 : 【贪心】时空定位II
题目描述
有一块空间,横向长w,纵向长为h,在它的横向中心线上不同位置处装有n(n≤10000)个点状的定位装置,每个定位装置i定位的效果是让以它为中心半径为Ri的圆都被覆盖。请在给出的定位装置中选择尽量少的定位装置,把整个空间全部覆盖。
输入
第一行输入一个正整数N表示共有n次测试数据。
每一组测试数据的第一行有三个整数n,w,h,n表示共有n个定位装置,w表示空间的横向长度,h表示空间的纵向长度。
随后的n行,都有两个整数xi和ri,xi表示第i个定位装置的横坐标(最左边为0),ri表示该定位装置能覆盖的圆的半径。
每一组测试数据的第一行有三个整数n,w,h,n表示共有n个定位装置,w表示空间的横向长度,h表示空间的纵向长度。
随后的n行,都有两个整数xi和ri,xi表示第i个定位装置的横坐标(最左边为0),ri表示该定位装置能覆盖的圆的半径。
输出
每组测试数据输出一个正整数,表示共需要多少个定位装置,每个输出单独占一行。
如果不存在一种能够把整个空间覆盖的方案,请输出0。
如果不存在一种能够把整个空间覆盖的方案,请输出0。
样例输入
2
2 8 6
1 1
4 5
2 10 6
4 5
6 5
样例输出
1
2
思路:求出每个区间的左右端点, 然后按左端点排序;
从左到右扫一遍就好。
#include <bits/stdc++.h> using namespace std; const int maxn = 605; struct uct { double left, right; }; bool cmp(uct a, uct b) { if(a.left == b.left) { return a.right > b.right; } return a.left < b.left; } int main() { ios::sync_with_stdio(false); uct s[maxn]; int n, t; cin >> t; while(t--) { double r, w, h, x; cin >> n >> w >> h; h = h*1.0/2; for(int i = 0; i < n; i++) { cin >> x >> r; if(r > h) { double y = r*r - h*h; s[i].left = max(x - sqrt(y), 0.0); s[i].right = min(x + sqrt(y), w); } else { s[i].left = x; s[i].right = x; } } sort(s, s+n, cmp); int cnt = 0; double start = 0; int i = -1; while(start < w && s[i+1].left <= start) { double MAX = -1; for(int j = i + 1; s[j].left <= start && j < n; j++) { if(MAX < s[j].right){ MAX = s[j].right; i = j; } } start = MAX; cnt++; } if(start >= w) cout << cnt << endl; else cout << 0 << endl; } return 0; }