题目
假设海岸是一条无限长的直线,陆地位于海岸的一侧,海洋位于另外一侧。
每个小岛都位于海洋一侧的某个点上。
雷达装置均位于海岸线上,且雷达的监测范围为 d,当小岛与某雷达的距离不超过 d 时,该小岛可以被雷达覆盖。
我们使用笛卡尔坐标系,定义海岸线为 x轴,海的一侧在 x轴上方,陆地一侧在 x 轴下方。
现在给出每个小岛的具体坐标以及雷达的检测范围,请你求出能够使所有小岛都被雷达覆盖所需的最小雷达数目。
输入格式
第一行输入两个整数 n 和 d,分别代表小岛数目和雷达检测范围。
接下来 n 行,每行输入两个整数,分别代表小岛的 x,y 轴坐标。
同一行数据之间用空格隔开。
输出格式
输出一个整数,代表所需的最小雷达数目,若没有解决方案则所需数目输出 −1−1。
数据范围
1≤n≤1000,
−1000≤x,y≤1000
输入样例:
3 2
1 2
-3 1
2 1
输出样例:
2
思路
- 数据范围是1000,所以只要不超过n^2就行
- 反向考虑:对于小岛来说,雷达要放在什么位置上才能照到小岛 ==》变成考虑区间
- 给定若干区间,最少选多少个点可以使得每个区间上至少选一个点;
- 贪心策略:
- 将所有区间按右端点排序
- 按照排序的顺序,扫描每个线段:
- 情况1:如果上一个点不在区间中,则选右端点;(右端点最有可能覆盖到后面的区间)
- 情况2:如果上一个点在区间中,则跳过;
- Python中的lambda
Python lambda(匿名函数) | 菜鸟教程 (runoob.com)
代码
import math
n, d = map(int, input().split())
segments = []
failed = False
for _ in range(n):
x, y = map(int, input().split())
if y > d:
failed = True
break
else:
lens= math.sqrt(d**2 - y**2)
segments.append((x - lens, x + lens))
if failed:
print("-1")
else:
segments.sort(key=lambda seg: seg[1]) # 使用lambda表达式按照右端点排序
cnt = 0
last = -1e20
for l, r in segments:
if last < l:
cnt += 1
last = r
print(cnt)