【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;
}
posted @ 2020-12-24 15:51  Jayun  阅读(106)  评论(0编辑  收藏  举报