大意是x轴上方有n个目标点,坐标全为整数,为了扫描到他们,在x轴上安放雷达,每一个雷达扫描半径为d,问至少安放多少雷达。
首先想到的是化归。找出每一点在x轴上的扫描边界,即在这个范围内必须有雷达才能扫描到。这样便将问题化归为:给n个闭区间,找出最少的点,保证每个区间至少有一个点。
贪心算法:我们先将问题的区间集合按右端点排序,从最左边的区间开始,如果该区间内雷达为空为空,则选区间最右边的端点放雷达,并删掉左端点在雷达前的区间,进入子问题。
//
// main.cpp
// poj1328
//
// Created by Fangpin on 15/5/21.
// Copyright (c) 2015年 FangPin. All rights reserved.
//
#include <iostream>
#include <vector>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
struct Node{
double l,r;
};
bool cmp(const Node& x,const Node& y){
return x.r<y.r;
}
int main(int argc, const char * argv[]) {
// insert code here...
// std::cout << "Hello, World!\n";
int n,d,ca=1;
while(scanf("%d%d",&n,&d),n+d){
vector<Node> vec;
vec.clear();
bool flag=true;
for(int i=0;i<n;++i){
int x,y;
scanf("%d%d",&x,&y);
if(y>d) flag=false;
vec.push_back(Node{x-sqrt(d*d-y*y),x+sqrt(d*d-y*y)});
}
if(!flag){
printf("Case %d: -1\n",ca++);
continue;
}
sort(vec.begin(),vec.end(),cmp);
int cnt=0;
double pre=-1e10;
for(int i=0;i<n;++i){
if(vec[i].l>pre){
pre=vec[i].r;
++cnt;
}
}
printf("Case %d: %d\n",ca++,cnt);
}
return 0;
}