【YBTOJ】【Luogu P1325】雷达安装 题目大意: 正文: 代码:

(n) 个点,第 (i) 个点的坐标是 ((x_i,y_i))。现在要你在 (x) 轴上标记若干个位置,使得每个点都能被一个以被标记位置为圆心,半径为 (d) 的圆覆盖。求最少标记多少位置。

正文:

首先任意一点如果的 (y) 坐标如果大于 (d),那么肯定覆盖不到,直接输出 -1

接下来考虑用贪心求解这个问题。

容易发现,点 (i) 要被覆盖,被覆盖的圆的圆心在 (x) 轴上,是一段区间,就是说此区间上的每一个点都能把点 (i) 覆盖。

既然如此,我们枚举点 (i) 的区间的右端点作为一个标记位置,当枚举到下一个点时,如果此标记位置在当前点区间内,则代表可以直接覆盖;如果不在,则用当前点的区间右端点作为新的标记位置。

代码:

const int N = 1010;

int n, m; 
struct Interval
{
	double l, r;
}a[N];

bool cmp (Interval a, Interval b)
{
	return a.r < b.r;
}

int main()
{
	scanf ("%d%d", &n, &m);
	for (int x, y, i = 1; i <= n; i++)
	{
		scanf ("%d%d", &x, &y);
		if(y > m) {puts("-1"); return 0;} 
		a[i].l = x * 1.0 - sqrt(m * m - y * y + 0.0);
		a[i].r = x * 1.0 + sqrt(m * m - y * y + 0.0);
	}
	sort (a + 1, a + 1 + n, cmp);
	double R = a[1].r;
	int ans = 1;
	for (int i = 2; i <= n; i++)
	{
		if (a[i].l <= R && R <= a[i].r) continue;
		else 
			ans ++, R = a[i].r;
	}
	printf ("%d", ans);
	return 0;
}