题目描述
给你一个炸弹列表。一个炸弹的 爆炸范围 定义为以炸弹为圆心的一个圆。
炸弹用一个下标从 0 开始的二维整数数组 bombs 表示,其中 bombs[i] = [xi, yi, ri] 。xi 和 yi 表示第 i 个炸弹的 X 和 Y 坐标,ri 表示爆炸范围的 半径 。
你需要选择引爆 一个 炸弹。当这个炸弹被引爆时,所有 在它爆炸范围内的炸弹都会被引爆,这些炸弹会进一步将它们爆炸范围内的其他炸弹引爆。
给你数组 bombs ,请你返回在引爆 一个 炸弹的前提下,最多 能引爆的炸弹数目。
2101.引爆最多的炸弹
测试案例及提示
示例1:
输入:bombs = [[2,1,3],[6,1,4]]
输出:2
解释:
上图展示了 2 个炸弹的位置和爆炸范围。
如果我们引爆左边的炸弹,右边的炸弹不会被影响。
但如果我们引爆右边的炸弹,两个炸弹都会爆炸。
所以最多能引爆的炸弹数目是 max(1, 2) = 2 。
示例 2:
输入:bombs = [[1,1,5],[10,10,5]]
输出:1
解释:
引爆任意一个炸弹都不会引爆另一个炸弹。所以最多能引爆的炸弹数目为 1 。
示例 3:
输入:bombs = [[1,2,3],[2,3,1],[3,4,2],[4,5,3],[5,6,4]]
输出:5
解释:
最佳引爆炸弹为炸弹 0 ,因为:
炸弹 0 引爆炸弹 1 和 2 。红色圆表示炸弹 0 的爆炸范围。
炸弹 2 引爆炸弹 3 。蓝色圆表示炸弹 2 的爆炸范围。
炸弹 3 引爆炸弹 4 。绿色圆表示炸弹 3 的爆炸范围。
所以总共有 5 个炸弹被引爆。
提示:
1 <= bombs.length <= 100
bombs[i].length == 3
1 <= xi, yi, ri <= 105
解题思路
转换问题,将每个炸弹看作图中的节点,而是否能通过一个炸弹引爆另一个炸弹看作是有向边。(不是无向边的原因是,炸弹a的爆炸范围波及炸弹b时,炸弹b的爆炸范围可能不能波及炸弹a。具体可看示例1中的两个炸弹)
因此可以先建立一个图,记录每个炸弹的爆炸波及情况。然后对于每个节点,使用DFS(深度优先遍历),就可找到引爆一颗炸弹可以波及的炸弹数了。
DFS入门可以看DFS图论
python
class Solution:
def maximumDetonation(self, bombs: List[List[int]]) -> int:
def canBoom(bomb1: List[int], bomb2: List[int]) -> List[int]:
ret = False
distancePow = pow((bomb1[0] - bomb2[0]), 2) + pow((bomb1[1] - bomb2[1]), 2)
if distancePow <= bomb1[-1] ** 2:
ret = True
return ret
n = len(bombs)
edges = defaultdict(list)
for i in range(n):
for j in range(n):
if i != j and canBoom(bombs[i], bombs[j]):
edges[i].append(j)
def dfs(node: int, visited: List[bool]) -> int:
visited[node] = True
count = 1
for neighbor in edges[node]:
if not visited[neighbor]:
count += dfs(neighbor, visited)
return count
ans = 0
for i in range(n):
visited = [False] * n
cnt = dfs(i, visited)
ans = max(ans, cnt)
return ans