[Luogu] UVA1193 Radar Installation

(Link)

Description

假设海岸线是一条无限长的直线,陆地位于海岸线的一边,大海位于海岸线的另一边。大海中有许多小岛。某安全部门为了监视这些岛上是否有敌人入侵,打算在海岸线上安装若干个雷达来检测岛屿的情况。每个雷达的覆盖范围是以雷达中心为圆心,半径为(d)的圆形区域。

我们用平面之间坐标系来表示整个区域,海岸线为(x)轴,大海位于(x)轴上方,陆地位于(x)轴下方。为了节约成本,安全部门想使用最少的雷达覆盖所有的岛屿。现在已知每个岛屿的坐标((x,y))和雷达的覆盖半径(d),你的任务就是计算出能够覆盖所有岛屿的最少雷达数量。

Solution

这道题的贪心思路就是对于一个未被覆盖的海岛,肯定是贪心地把雷达放在能覆盖到它的最右边的地方。但是排序不是按(x)坐标排序,而是按r排序,因为(r)越小,把雷达放在(r)能覆盖到的岛屿(之前的)就会更多,如果(r)比较大,就可能会漏掉前面的一些岛屿,且我们是按(r)贪心,肯定也要按(r)排序。

然后这题要开(double),注意实数比较大小会有误差,要用(eps)

Code

#include <bits/stdc++.h>

using namespace std;

const double eps = 1e-6;

int n, t, bk[1005];

struct node
{
	double x, y, r;
}p[1005];

double d;

int read()
{
	int x = 0, fl = 1; char ch = getchar();
	while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
	return x * fl;
}

int cmp(node a, node b)
{
	return a.r < b.r || (a.r == b.r && a.y > b.y);
}

int main()
{
	while (1)
	{
		n = read(); scanf("%lf", &d);
		if ((!n) && (!d)) break;
		double mx = 0;
		for (int i = 1; i <= n; i ++ )
		{
			scanf("%lf %lf", &p[i].x, &p[i].y);
			mx = max(mx, p[i].y);
			p[i].r = p[i].x + sqrt(d * d - p[i].y * p[i].y);
		}
		sort(p + 1, p + n + 1, cmp);
		t ++ ;
		printf("Case %d: ", t);
		if (mx > d)
		{
			puts("-1");
			continue;
		}
		double pos;
		int res = 0;
		for (int i = 1; i <= n; i ++ )
		{
			pos = p[i].x + sqrt(d * d - p[i].y * p[i].y);
			res ++ ;
			for (int j = i + 1; j <= n; j ++ )
			{
				i = j;
				if (p[j].y * p[j].y + (pos - p[j].x) * (pos - p[j].x) - d * d > eps)
				{
					i -- ;
					break;
				}
			}
		}
		printf("%d
", res);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/andysj/p/14032013.html