贪心-放置雷达
Radar Installation:x轴是海岸线, x 轴上方是海洋。海洋中有 n
1<=n<=1000) 个岛屿,可以看作点。给定每个岛屿的坐标(x,y)x,y都是整
数。当一个雷达(可以看作点)到岛屿的距离不超过 d(整数),则认为该雷达
覆盖了该岛屿。雷达只能放在x轴上。问至少需要多少个雷达才可以覆盖全部岛屿。
Sample Input:3个岛,距离d=2,后面3组数描述3个岛的坐标
3 2
1 2
-3 1
2 1
Sample Output:至少需要雷达的数量
2
原理:对每个岛屿P, 可以算出,覆盖它的雷达,必须位于 x 轴上的区间 Ps ,Pe 。
如果有雷达位于某个x轴区间 [a,b ],称该雷达覆盖此区间。问题转换为,
至少要在 x 轴上放几个雷达(点),才能覆盖全部区间 [P1s ,P1e],
[P2s,P2e ……Pns,Pne]
重要结论:如果可以找到一个雷达同时覆盖多个区间,那么把这多个区间按起点坐
标从小到大排序 ,则最后一个区间 起点最靠右的k的起点,就能覆盖所有区间
规则:只需要存储当前右端点的最小值,判断新加入坐标的左端点是否大于当前右端点
的最小值;
1)如果小于等于,则说明可以覆盖,彼此有公共区域,不需要新增雷达,同时需要更新
一下右端点的最小值
2)如果大于,说明没有公共的交点,需要新增雷达,右端点的最小值为新加入的雷达右端点
Python代码实现:
1 import math 2 3 4 def main(): 5 # 雷达的数量 6 radar_num = 1 7 # 岛屿列表 8 island_list = [] 9 n, d = map(int, input().split()) 10 for i in range(n): 11 temp = list(map(int, input().split())) 12 # 计算该岛映射到x轴左右端点的值 13 left_pos = temp[0] - math.sqrt(math.pow(d, 2) - math.pow(temp[1], 2)) 14 right_pos = temp[0] + math.sqrt(math.pow(d, 2) - math.pow(temp[1], 2)) 15 temp.append(round(left_pos, 2)) 16 temp.append(round(right_pos, 2)) 17 island_list.append(temp) 18 # [[1, 2, 1.0, 1.0], 19 # [-3, 1, -4.73, -1.27], 20 # [2, 1, 0.27, 3.73]] 21 # 以岛屿列表的左端点进行排序 22 island_list = sorted(island_list, key=lambda x: x[2]) 23 # 当前岛屿右端点的最小值 24 min_right = island_list[0][3] 25 for i in range(1, n): 26 # 如果新加入的岛屿左端点<这组集合右端点的值,说明可以在同一个雷达覆盖范围 27 # 则不需要新增雷达,此时可能需要更新右端点的最小值 28 if island_list[i][2] <= min_right: 29 min_right = min(min_right, island_list[i][3]) 30 # 大于的话,说明不能与前一组岛屿共用同一个雷达,需要新增一个雷达 31 # 右端的最小值也需要重新更新 32 else: 33 min_right = island_list[i][3] 34 radar_num += 1 35 36 print("至少需要%d个雷达" % radar_num) 37 return 0 38 39 40 if __name__ == '__main__': 41 main()