贪心。
一开始的思路:
图中ABCD为海岛的位置。假设本题半径为2(符合坐标系),那么A点坐标为(1,1)以此类推。
在题中,记录每个点的坐标,并把一个点新加一个标记变量以标记是否被访问过。
首先以A为圆心,r为半径做圆,交x轴与E1(右)点,做出如图中绿色虚线圆。然后以E1为圆心,半径为r做圆。看此时下一点(B)是否在该圆中。如果在,那么将该点标记变量变为true,再判下一点(C),如果不在那么就新增一个雷达。
后来,换了思路,存储图中红色圆与X轴的交点。
还是原来的贪心思路,仍然先排序,但排序的准则是按红色圆与x轴左交点的先后顺序。
如图,如果B点圆(且如此称呼)的左交点(J1点)在A点圆右交点(E1)左侧,那么B点一定涵盖在A点圆内部。再如图,如果D点圆的左交点(图中未标示)在A点圆的右交点(未标示)右,则D点不在A点圆中。
故,有如下代码:
#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
using namespace std;
struct point
{
double left, right;
}p[2010], temp;
bool operator < (point a, point b)
{
return a.left < b.left;
}
int main()
{
int n;
double r;
int kase = 0;
while (cin >> n >> r && (n || r))
{
bool flag = false;
for (int i = 0; i < n; i++)
{
double a, b;
cin >> a >> b;
if (fabs(b) > r)
{
flag = true;
}
else
{
p[i].left = a * 1.0 - sqrt(r * r - b * b);
p[i].right = a * 1.0 + sqrt(r * r - b * b);
}
}
cout << "Case " << ++kase << ": ";
if (flag)
{
cout << -1 << endl;
}
else
{
int countt = 1;
sort(p, p + n);
temp = p[0];
for (int i = 1; i < n; i++)
{
if (p[i].left > temp.right)
{
countt++;
temp = p[i];
}
else if (p[i].right < temp.right)
{
temp = p[i];
}
}
cout << countt << endl;
}
}
}