Problem Description
我们假设海岸线是一条无限直线:以海岸线为界,陆地和海洋被分开,在海边分布着很多小岛。现在,我们在海岸线上安装雷达,每个雷达有固定的通讯范围(以d为半径的圆形区域),这样,海边的小岛就可以被某个雷达信号覆盖。
这里我们使用笛卡尔坐标系,定义海岸线为x轴,x轴上方是海洋,下方是陆地。给出分布在海边每个小岛的坐标位置和雷达信号能覆盖的范围d,你的任务是计算出最小需要安装的雷达数目,使得这些雷达信号能覆盖到所有海边的小岛。每个小岛的坐标格式为(x,y)。
如下图所示,给出第一个输入样例的坐标表示,这样在(-2,0),(1,0)上分别安装雷达就可以覆盖所有的小岛(p点),所以我们只需要安装2个雷达。
Input
输入包含多组测试样例。每组测试第一行包含两个整数n(1<=n<=1000)和d,n表示小岛的数目,d表示雷达能覆盖的范围的半径。接下来n行,每行由整数x和y组成,表示n个小岛的坐标位置。每两组数据之间有一个空行。
输入0 0表示输入的结束。Output
对于每一组输入,按照输出样例中的格式输出:包含输出序号和最少需要安装雷达的数目。如果找不到解决方案,即不能找到一种安装方案覆盖所有的小岛,输出”-1”。
Sample Input
3 2 1 2 -3 1 2 1 1 2 0 2 0 0Sample Output
Case 1: 2 Case 2: 1
#include<cstdio> #include<cmath> #include<algorithm> #define fi first // 宏定义 为了代码简便 #define se second // 分别表示pair中的第一个数和第二个数 using namespace std; const int maxn = 1e5+5; pair<double, double> a[maxn]; int main() { int n, d, cs = 1; while(~scanf("%d%d", &n, &d) && n){ double x, y; bool can = true; for(int i=0; i<n; i++){ scanf("%lf%lf", &x, &y); if(y > d || y < -d) { // 无法覆盖的点 can = false; continue; } a[i].fi = x - sqrt(d*d - y*y); // 可覆盖第i个点,在x轴上最左侧的位置 a[i].se = x + sqrt(d*d - y*y); // 可覆盖第i个点,在x轴上最右侧的位置 } printf("Case %d: ", cs++); if(!can) { puts("-1"); continue; } int cnt = 1; sort(a, a+n); // 默认按照第一个数升序优先,第二个数升序的顺序排序 pair<double, double> now = a[0]; // 初始化可用区间 for(int i=1; i<n; i++){ if(now.se < a[i].fi) { // 当前区间不能覆盖a[i] 更新可能区间 cnt ++; now = a[i]; } else if(now.se > a[i].se) now = a[i]; // 当前区间过大,需要减小可用区间 } printf("%d\n", cnt); } return 0; }