题干:

Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point locating in the sea side. And any radar installation, locating on the coasting, can only cover d distance, so an island in the sea can be covered by a radius installation, if the distance between them is at most d. 

We use Cartesian coordinate system, defining the coasting is the x-axis. The sea side is above x-axis, and the land side below. Given the position of each island in the sea, and given the distance of the coverage of the radar installation, your task is to write a program to find the minimal number of radar installations to cover all the islands. Note that the position of an island is represented by its x-y coordinates. 
<center>  
Figure A Sample Input of Radar Installations </center>

Input
The input consists of several test cases. The first line of each case contains two integers n (1<=n<=1000) and d, where n is the number of islands in the sea and d is the distance of coverage of the radar installation. This is followed by n lines each containing two integers representing the coordinate of the position of each island. Then a blank line follows to separate the cases. 

The input is terminated by a line containing pair of zeros 
Output
For each test case output one line consisting of the test case number followed by the minimal number of radar installations needed. "-1" installation means no solution for that case.
Sample Input
3 2
1 2
-3 1
2 1

1 2
0 2

0 0
Sample Output
Case 1: 2
Case 2: 1


题目大意:

    在x轴上建造雷达,似的x轴上方的所有岛屿都能被辐射到。每个雷达的辐射半径已知,求:为使所有岛屿都被辐射到,所需要的最少雷达个数。

解题报告:

    这应该说是我遇到的第二个不算很水的计算几何问题,上一个是 解救雅典娜,用dp做,这一题是用贪心做。先按照x坐标从小到大排序,先确定一个半完成值(half-finish自己取的名,第一次使用是在这里)圆心setx,然后逐个遍历圆心curx(这里取右圆心)(因为圆的半径已知为d,所以圆心的x轴坐标显然可求),如果curx<=setx 显然要取curx 为圆心的那个圆,因为这样两个岛屿都会被包进去。如果curx>setx 那就要比较一下该点到圆心setx的距离是否大于d,如果小于等于d,那虚惊一场可以辐射到这个岛,如果大于d,那凉凉,只能新建一个雷达了所以ans++。遍历完所有岛屿即可得出答案ans。(但是总觉得不严谨,因为你虽然这个点(记为A)到圆心(记为setx1)的距离大于d了,你就更新了setx(更新为setx2),但有可能下一个点(记为B)满足curx>setx1&&到圆心的距离<=d呢?,所以不应该这么着急着更新setx吧,,,因为你不确定B是不是也不满足小于等于d这个要求啊)

对上面问题的回答:是这样的,确实保证不了,但是因为你已经有一个A满足不了了,所以无论如何你也要为了A岛屿而建立一个雷达,而这个新雷达能否包含B就看B这个的坐标了。。。即:题目只问的是最少需要建几个雷达,而非让你把每个岛屿属于哪个雷达说清楚,因此没必要考虑这些问题。


ac代码:

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

struct Node {
	int x, y;
} node[1000 + 5];

bool cmp(const Node & a,const Node & b) {
	return a.x<b.x;//此题y坐标排不排序无所谓的、、、	
	
}

int main()
{
	int n,d;
	int ans=1;
	int maxy;
	int iCase=0;
	double curx,setx,seti;//curx表示当前尝试的右圆心  setx表示当前确定的右圆心  seti表示当前确定的索引值 
	double curd;//curd表示当前尝试的圆的半径 
	while(scanf("%d %d",&n,&d)) {
		ans=1;
		maxy=0;//别忘了初始化! ! 
		if(n==0 && d==0) break;
		for(int i = 0; i<n; i++) {
			scanf("%d %d",&node[i].x,&node[i].y);	
			maxy=max(node[i].y,maxy);
		}
		if(maxy>d) {
			printf("Case %d: -1\n" , ++iCase);
			continue;
		}
		sort(node,node+n,cmp);
		curx=node[0].x+sqrt(d*d-( node[0].y )*( node[0].y ) );
		setx=curx;
		seti=0;
		for(int i = 1; i<n; i++) {//因为第一个已经初始化好了,所以下标从1开始 
			curx=node[i].x+sqrt(d*d-( node[i].y )*( node[i].y ) );
			if(curx<=setx) {
				setx=curx;
			}
			else {
				curd=sqrt( (node[i].x-setx)*(node[i].x-setx) +(node[i].y)*(node[i].y) );
				if(curd<=d) {
					continue;
				}
				else {
					ans++;
					setx=curx;
				}
			}
		}	
		printf("Case %d: %d\n",++iCase,ans);
	} 
	return 0 ;
}

下面附上kuangbin大佬的代码:(其实差不多的只不过我是用的点到setx的距离d,他是用的点的左圆心)

#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>//sort所在的库文件,排序用
using namespace std;
const int MAXN=1005;
struct Line
{
    double l,r;
}line[MAXN];//每个岛作半径为d的圆,与x轴所截的线段

bool cmp(Line a,Line b)
{
    
    return a.l<b.l;
}       //按照线段的左端点从小到大排序
int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    int n,d;
    int i;
    int x,y;
    bool yes;//确定是不是有解
    int icase=1;
    while(cin>>n>>d)
    {
        yes=true;
        int cnt=0;
        if(n==0&&d==0)break;
        for(i=0;i<n;i++)
        {
            cin>>x>>y;
            if(yes==false)continue;
            if(y>d)yes=false;
            else
            {
                line[i].l=(double)x-sqrt((double)d*d-y*y);
                line[i].r=(double)x+sqrt((double)d*d-y*y);
            }    
        }
        if(yes==false)
        {
            cout<<"Case "<<icase++<<": -1"<<endl;
            continue;
        }
        sort(line,line+n,cmp);
        cnt++;
        double now=line[0].r;
        for(i=1;i<n;i++)
        {
            
            if(line[i].r<now)//这点很重要 
               now=line[i].r;
            else if(now<line[i].l)
            {
                now=line[i].r;
                cnt++;
            }    
        }
        cout<<"Case "<<icase++<<": "<<cnt<<endl;    
                
    }     
    return 0;
}