Detonate the Maximum Bombs
Build edge i to j iff bomb i reaches bomb j; BFS/DFS from each source and take the max reachable.
5 min read
geometry graph bfs dfs
Problem#
Each bomb has a 2D position and radius. Detonating one triggers others within its radius, which trigger their own neighbors. Pick a starting bomb to maximize the total detonated.
Examples#
[[2,1,3],[6,1,4]]→2.[[1,1,5],[10,10,5]]→1.
Constraints#
1 <= bombs.length <= 100.
Approach#
Build a directed graph: edge i → j iff bomb j lies inside bomb i’s radius (squared distance test). BFS/DFS from each bomb to count reachable; return the max.
Solution#
class Solution {public: int maximumDetonation(vector<vector<int>>& bombs) { int n = bombs.size(); vector<vector<int>> adj(n); for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) if (i != j) { long long dx = bombs[i][0] - bombs[j][0]; long long dy = bombs[i][1] - bombs[j][1]; long long r = bombs[i][2]; if (dx * dx + dy * dy <= r * r) adj[i].push_back(j); } int best = 0; for (int s = 0; s < n; ++s) { vector<int> vis(n, 0); vis[s] = 1; queue<int> q; q.push(s); int cnt = 0; while (!q.empty()) { int u = q.front(); q.pop(); ++cnt; for (int v : adj[u]) if (!vis[v]) { vis[v] = 1; q.push(v); } } best = max(best, cnt); } return best; }};func maximumDetonation(bombs [][]int) int { n := len(bombs) adj := make([][]int, n) for i := 0; i < n; i++ { for j := 0; j < n; j++ { if i == j { continue } dx := int64(bombs[i][0] - bombs[j][0]) dy := int64(bombs[i][1] - bombs[j][1]) r := int64(bombs[i][2]) if dx*dx+dy*dy <= r*r { adj[i] = append(adj[i], j) } } } best := 0 for s := 0; s < n; s++ { vis := make([]bool, n) vis[s] = true q := []int{s} cnt := 0 for len(q) > 0 { u := q[0] q = q[1:] cnt++ for _, v := range adj[u] { if !vis[v] { vis[v] = true q = append(q, v) } } } if cnt > best { best = cnt } } return best}from collections import dequefrom typing import List
class Solution: def maximumDetonation(self, bombs: List[List[int]]) -> int: n = len(bombs) adj: List[List[int]] = [[] for _ in range(n)] for i in range(n): for j in range(n): if i == j: continue dx = bombs[i][0] - bombs[j][0] dy = bombs[i][1] - bombs[j][1] r = bombs[i][2] if dx * dx + dy * dy <= r * r: adj[i].append(j) best = 0 for s in range(n): vis = [False] * n vis[s] = True q = deque([s]) cnt = 0 while q: u = q.popleft() cnt += 1 for v in adj[u]: if not vis[v]: vis[v] = True q.append(v) if cnt > best: best = cnt return bestvar maximumDetonation = function(bombs) { const n = bombs.length; const adj = Array.from({ length: n }, () => []); for (let i = 0; i < n; i++) { for (let j = 0; j < n; j++) { if (i === j) continue; const dx = bombs[i][0] - bombs[j][0]; const dy = bombs[i][1] - bombs[j][1]; const r = bombs[i][2]; if (dx * dx + dy * dy <= r * r) adj[i].push(j); } } let best = 0; for (let s = 0; s < n; s++) { const vis = new Array(n).fill(false); vis[s] = true; const q = [s]; let head = 0, cnt = 0; while (head < q.length) { const u = q[head++]; cnt++; for (const v of adj[u]) { if (!vis[v]) { vis[v] = true; q.push(v); } } } if (cnt > best) best = cnt; } return best;};class Solution { public int maximumDetonation(int[][] bombs) { int n = bombs.length; List<List<Integer>> adj = new ArrayList<>(); for (int i = 0; i < n; i++) adj.add(new ArrayList<>()); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i == j) continue; long dx = bombs[i][0] - bombs[j][0]; long dy = bombs[i][1] - bombs[j][1]; long r = bombs[i][2]; if (dx * dx + dy * dy <= r * r) adj.get(i).add(j); } } int best = 0; for (int s = 0; s < n; s++) { boolean[] vis = new boolean[n]; vis[s] = true; Deque<Integer> q = new ArrayDeque<>(); q.offer(s); int cnt = 0; while (!q.isEmpty()) { int u = q.poll(); cnt++; for (int v : adj.get(u)) { if (!vis[v]) { vis[v] = true; q.offer(v); } } } best = Math.max(best, cnt); } return best; }}function maximumDetonation(bombs: number[][]): number { const n = bombs.length; const adj: number[][] = Array.from({ length: n }, () => []); for (let i = 0; i < n; i++) { for (let j = 0; j < n; j++) { if (i === j) continue; const dx = bombs[i][0] - bombs[j][0]; const dy = bombs[i][1] - bombs[j][1]; const r = bombs[i][2]; if (dx * dx + dy * dy <= r * r) adj[i].push(j); } } let best = 0; for (let s = 0; s < n; s++) { const vis = new Array<boolean>(n).fill(false); vis[s] = true; const q: number[] = [s]; let head = 0, cnt = 0; while (head < q.length) { const u = q[head++]; cnt++; for (const v of adj[u]) { if (!vis[v]) { vis[v] = true; q.push(v); } } } if (cnt > best) best = cnt; } return best;}Editorial#
The relation “i triggers j” is directed because bomb radii differ — i may cover j without j covering i. Squared-distance comparison avoids floats. Trying every starting bomb is O(n) BFSes, each O(n + edges) — well within the n <= 100 budget.
Complexity#
- Time:
O(n^2)graph build +O(n * (n + e))BFS. - Space:
O(n^2).
Concept revision#
Related#