本题是贪心法题解。只是须要自己观察出规律。这就不easy了,非常easy出错。
一般网上做法是找区间的方法。
这里给出一个独特的方法:
1 依照x轴大小排序
2 从最左边的点循环。首先找到最小x轴的圆
3 以这个圆推断能够包含右边的多少个圆,直到不能够包含下一个点,那么继续第2步,画一个新圆。
看代码吧,应该非常清晰直观的了。
效率是O(n),尽管有嵌套循环。可是下标没有反复。一遍循环就能够了。故此是O(n)。
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <float.h>
using namespace std;
const int MAX_N = 1001;
inline float MAX(float a, float b) { return a > b ? a : b; }
inline float MIN(float a, float b) { return a < b ?
a : b; }
struct Point
{
float x, y;
bool operator<(const Point &p) const
{
if (x == p.x) return y > p.y;
return x < p.x;
}
float dist(const Point &p) const
{
float a = (x - p.x);
float b = (y - p.y);
return sqrtf(a*a+b*b);
}
float dist(const float x1, const float y1) const
{
float a = (x - x1);
float b = (y - y1);
return sqrtf(a*a+b*b);
}
};
Point ps[MAX_N];
int calRadar(int n, int d)
{
sort(ps, ps+n);
float cenX = 0.0f, cenY = 0.0f;
int ans = 0;
for (int i = 0; i < n; ) //视情况而添加i
{
ans++;
float dx = sqrtf(float(d*d) - ps[i].y*ps[i].y);
cenX = ps[i].x + dx;
for (i++; i < n && ps[i].x <= cenX; i++)
{
dx = sqrtf(float(d*d) - ps[i].y*ps[i].y);
cenX = MIN(cenX, ps[i].x + dx);
}
float dis = 0.0f;
for ( ; i < n; i++)
{
dis = ps[i].dist(cenX, cenY);
if (dis > float(d)) break;
}
}
return ans;
}
int main()
{
int n, d, t = 1;
while (scanf("%d %d", &n, &d) && (n || d))
{
float maxY = FLT_MIN;//这个放外面了,错误!
for (int i = 0; i < n; i++)
{
scanf("%f %f", &ps[i].x, &ps[i].y);
maxY = MAX(ps[i].y, maxY);
}
if (maxY > (float)d) printf("Case %d: -1
", t++);
else printf("Case %d: %d
", t++, calRadar(n, d));
}
return 0;
}