1. 程式人生 > 實用技巧 >[Luogu] UVA1193 Radar Installation

[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\n", res);
	}
	return 0;
}