题目链接:http://poj.org/problem?id=1328
题目大意就是雷达覆盖问题。给你几座岛的位置,求至少几座覆盖半径为r的雷达可以全部覆盖这些岛。
这是一道很经典的贪心问题,但是刚开始并不容易想出来。
刚开始我们能想到的是,如果一座岛能够在某个圆的边上,那么就尽量让它呆在边上,这样那个圆才能更广的去覆盖其他的点。所以我们首先要思考的是能让这个岛位于圆的边缘的那个圆心的坐标范围应该是怎么样的。
通过画图我们可以很容易的看出,假设某个岛的坐标是(x,y),圆的半径是r,那么能够覆盖到这个点的圆心范围应该是[x-sqrt(r*r-y*y),x+sqrt(r*r-y*y)].求出每座岛的圆心范围后,我们的策略就是将这些圆心的范围按照最左边的那个值从小到大进行排序,即按照x-sqrt(r*r-y*y),这样子排好序以后,我们就可以模拟一遍进行求解了。
首先我们第一个画的圆应该位于a[0].left-a[0].right之间,那么对于下一个点a[1],如果a[1]的left (也就是能够覆盖到a[1]这个点圆心最左边的位置)小于当前圆心的最大值,那么说明第一个圆最多只能覆盖第一个点,此时我们得再画一个圆来覆盖a[1],并且把当前圆的范围更改为a[1]的范围;除了上述情况,还有一种情况是a[1]的right(也就是能够覆盖到a[1]这个点圆心最右的位置)小于当前点的最右边位置,此时我们把圆画在a[1].right位置就行,因为这个圆也能覆盖到a[0]这个点,但是我们要注意此时圆的最右边就是由a[1]定下来的,所以要把当前的圆更新为a[1]。其他情况对结果无关。
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<time.h>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<limits.h>
#include<map>
#include<set>
//#define ONLINE_JUDGE
#define eps 1e-8
#define INF 0x7fffffff
#define FOR(i,a) for((i)=0;i<(a);(i)++)
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c)scanf("%d%d%d",&a,&b,&c)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
const double PI=acos(-1.0);
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
using namespace std;
#define ll __int64
int n,m,r;
#define N 110
struct Node{
double left,right;
bool operator <(const Node &x)const{
return left<x.left;
}
}a[1010];
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
int kas=1;
while(sfd(n,r)!=EOF&&n+r){
int x,y;
int flag=1;
for(int i=0;i<n;i++){
sfd(x,y);
if(y>r)
flag=0;
if(r>=y){
a[i].left = x*1.0 - sqrt(r*r*1.0-y*y*1.0);
a[i].right = x*1.0 + sqrt(r*r*1.0-y*y*1.0);
}
}
printf("Case %d: ",kas++);
if(!flag){
printf("-1\n");
}else{
sort(a,a+n);
Node tmp = a[0];
int ans=1;
for(int i=1;i<n;i++){
if(a[i].left>tmp.right){<span style="white-space:pre"> </span>//第一种情况
ans++;
tmp = a[i];
}else if(a[i].right<tmp.right)<span style="white-space:pre"> </span>//第二种情况
tmp = a[i];
}
printf("%d\n",ans);
}
}
return 0;
}