Skip to content

Commit cf894ad

Browse files
authored
feat: add solutions to lc problem: No.3661 (#4664)
No.3661.Maximum Walls Destroyed by Robots
1 parent 3637d4b commit cf894ad

File tree

7 files changed

+723
-9
lines changed

7 files changed

+723
-9
lines changed

solution/3600-3699/3661.Maximum Walls Destroyed by Robots/README.md

Lines changed: 248 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,32 +101,275 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3600-3699/3661.Ma
101101

102102
<!-- solution:start -->
103103

104-
### 方法一
104+
### 方法一:记忆化搜索
105105

106-
<!-- tabs:start -->
106+
我们首先将每个机器人与其射程一起存储在一个数组中,并按照机器人的位置进行排序。同时,我们对墙壁的位置进行排序。接下来,我们使用深度优先搜索(DFS)来计算每个机器人可以摧毁的墙壁数量,并使用记忆化搜索来避免重复计算。
107+
108+
我们设计一个函数 $\text{dfs}(i, j)$,其中 $i$ 表示当前考虑的机器人索引,而 $j$ 表示下一个机器人的发射方向(0 表示左,1 表示右)的时候,所能摧毁的墙壁数量。答案为 $\text{dfs}(n - 1, 1)$,边界状态下的 $j$ 可以取 0 或 1。
109+
110+
函数 $\text{dfs}(i, j)$ 的执行逻辑如下:
111+
112+
如果 $i \lt 0$,表示所有机器人都已经考虑过,返回 0。
113+
114+
否则,对于当前机器人,有两种发射方向可供选择。
115+
116+
如果选择**向左**发射,我们需要计算左侧的射程范围 $[\text{left}, \text{robot}[i][0]]$,并通过二分查找,计算此范围内可以摧毁的墙壁数量。这种情况下一共可以摧毁 $\text{dfs}(i - 1, 0) + \text{count}$ 墙壁,其中 $\text{count}$ 是当前机器人向左发射时摧毁的墙壁数量。
117+
118+
如果选择**向右**发射,我们需要计算右侧的射程范围 $[\text{robot}[i][0], \text{right}]$,并通过二分查找,计算此范围内可以摧毁的墙壁数量。这种情况下一共可以摧毁 $\text{dfs}(i - 1, 1) + \text{count}$ 墙壁,其中 $\text{count}$ 是当前机器人向右发射时摧毁的墙壁数量。
119+
120+
函数的返回值为两种发射方向所能摧毁墙壁数量的最大值。
121+
122+
时间复杂度 $O(n \times \log n + m \times \log m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是机器人和墙壁的数量。
107123

108124
#### Python3
109125

110126
```python
111-
127+
class Solution:
128+
def maxWalls(self, robots: List[int], distance: List[int], walls: List[int]) -> int:
129+
n = len(robots)
130+
arr = sorted(zip(robots, distance), key=lambda x: x[0])
131+
walls.sort()
132+
133+
@cache
134+
def dfs(i: int, j: int) -> int:
135+
if i < 0:
136+
return 0
137+
left = arr[i][0] - arr[i][1]
138+
if i > 0:
139+
left = max(left, arr[i - 1][0] + 1)
140+
l = bisect_left(walls, left)
141+
r = bisect_left(walls, arr[i][0] + 1)
142+
ans = dfs(i - 1, 0) + r - l
143+
right = arr[i][0] + arr[i][1]
144+
if i + 1 < n:
145+
if j == 0:
146+
right = min(right, arr[i + 1][0] - arr[i + 1][1] - 1)
147+
else:
148+
right = min(right, arr[i + 1][0] - 1)
149+
l = bisect_left(walls, arr[i][0])
150+
r = bisect_left(walls, right + 1)
151+
ans = max(ans, dfs(i - 1, 1) + r - l)
152+
return ans
153+
154+
return dfs(n - 1, 1)
112155
```
113156

114157
#### Java
115158

116159
```java
117-
160+
class Solution {
161+
private Integer[][] f;
162+
private int[][] arr;
163+
private int[] walls;
164+
private int n;
165+
166+
public int maxWalls(int[] robots, int[] distance, int[] walls) {
167+
n = robots.length;
168+
arr = new int[n][2];
169+
for (int i = 0; i < n; i++) {
170+
arr[i][0] = robots[i];
171+
arr[i][1] = distance[i];
172+
}
173+
Arrays.sort(arr, Comparator.comparingInt(a -> a[0]));
174+
Arrays.sort(walls);
175+
this.walls = walls;
176+
f = new Integer[n][2];
177+
return dfs(n - 1, 1);
178+
}
179+
180+
private int dfs(int i, int j) {
181+
if (i < 0) {
182+
return 0;
183+
}
184+
if (f[i][j] != null) {
185+
return f[i][j];
186+
}
187+
188+
int left = arr[i][0] - arr[i][1];
189+
if (i > 0) {
190+
left = Math.max(left, arr[i - 1][0] + 1);
191+
}
192+
int l = lowerBound(walls, left);
193+
int r = lowerBound(walls, arr[i][0] + 1);
194+
int ans = dfs(i - 1, 0) + (r - l);
195+
196+
int right = arr[i][0] + arr[i][1];
197+
if (i + 1 < n) {
198+
if (j == 0) {
199+
right = Math.min(right, arr[i + 1][0] - arr[i + 1][1] - 1);
200+
} else {
201+
right = Math.min(right, arr[i + 1][0] - 1);
202+
}
203+
}
204+
l = lowerBound(walls, arr[i][0]);
205+
r = lowerBound(walls, right + 1);
206+
ans = Math.max(ans, dfs(i - 1, 1) + (r - l));
207+
return f[i][j] = ans;
208+
}
209+
210+
private int lowerBound(int[] arr, int target) {
211+
int idx = Arrays.binarySearch(arr, target);
212+
if (idx < 0) {
213+
return -idx - 1;
214+
}
215+
return idx;
216+
}
217+
}
118218
```
119219

120220
#### C++
121221

122222
```cpp
123-
223+
class Solution {
224+
public:
225+
int maxWalls(vector<int>& robots, vector<int>& distance, vector<int>& walls) {
226+
int n = robots.size();
227+
vector<pair<int, int>> arr(n);
228+
for (int i = 0; i < n; i++) {
229+
arr[i] = {robots[i], distance[i]};
230+
}
231+
ranges::sort(arr, {}, &pair<int, int>::first);
232+
ranges::sort(walls);
233+
234+
vector f(n, vector<int>(2, -1));
235+
236+
auto dfs = [&](this auto&& dfs, int i, int j) -> int {
237+
if (i < 0) {
238+
return 0;
239+
}
240+
if (f[i][j] != -1) {
241+
return f[i][j];
242+
}
243+
244+
int left = arr[i].first - arr[i].second;
245+
if (i > 0) {
246+
left = max(left, arr[i - 1].first + 1);
247+
}
248+
int l = ranges::lower_bound(walls, left) - walls.begin();
249+
int r = ranges::lower_bound(walls, arr[i].first + 1) - walls.begin();
250+
int ans = dfs(i - 1, 0) + (r - l);
251+
252+
int right = arr[i].first + arr[i].second;
253+
if (i + 1 < n) {
254+
if (j == 0) {
255+
right = min(right, arr[i + 1].first - arr[i + 1].second - 1);
256+
} else {
257+
right = min(right, arr[i + 1].first - 1);
258+
}
259+
}
260+
l = ranges::lower_bound(walls, arr[i].first) - walls.begin();
261+
r = ranges::lower_bound(walls, right + 1) - walls.begin();
262+
ans = max(ans, dfs(i - 1, 1) + (r - l));
263+
264+
return f[i][j] = ans;
265+
};
266+
267+
return dfs(n - 1, 1);
268+
}
269+
};
124270
```
125271

126272
#### Go
127273

128274
```go
275+
func maxWalls(robots []int, distance []int, walls []int) int {
276+
type pair struct {
277+
x, d int
278+
}
279+
n := len(robots)
280+
arr := make([]pair, n)
281+
for i := 0; i < n; i++ {
282+
arr[i] = pair{robots[i], distance[i]}
283+
}
284+
sort.Slice(arr, func(i, j int) bool {
285+
return arr[i].x < arr[j].x
286+
})
287+
sort.Ints(walls)
288+
289+
f := make(map[[2]int]int)
290+
291+
var dfs func(int, int) int
292+
dfs = func(i, j int) int {
293+
if i < 0 {
294+
return 0
295+
}
296+
key := [2]int{i, j}
297+
if v, ok := f[key]; ok {
298+
return v
299+
}
300+
301+
left := arr[i].x - arr[i].d
302+
if i > 0 {
303+
left = max(left, arr[i-1].x+1)
304+
}
305+
l := sort.SearchInts(walls, left)
306+
r := sort.SearchInts(walls, arr[i].x+1)
307+
ans := dfs(i-1, 0) + (r - l)
308+
309+
right := arr[i].x + arr[i].d
310+
if i+1 < n {
311+
if j == 0 {
312+
right = min(right, arr[i+1].x-arr[i+1].d-1)
313+
} else {
314+
right = min(right, arr[i+1].x-1)
315+
}
316+
}
317+
l = sort.SearchInts(walls, arr[i].x)
318+
r = sort.SearchInts(walls, right+1)
319+
ans = max(ans, dfs(i-1, 1)+(r-l))
320+
321+
f[key] = ans
322+
return ans
323+
}
324+
325+
return dfs(n-1, 1)
326+
}
327+
```
129328

329+
#### TypeScript
330+
331+
```ts
332+
function maxWalls(robots: number[], distance: number[], walls: number[]): number {
333+
type Pair = [number, number];
334+
const n = robots.length;
335+
const arr: Pair[] = robots.map((r, i) => [r, distance[i]]);
336+
337+
_.sortBy(arr, p => p[0]).forEach((p, i) => (arr[i] = p));
338+
walls.sort((a, b) => a - b);
339+
const f: number[][] = Array.from({ length: n }, () => Array(2).fill(-1));
340+
341+
function dfs(i: number, j: number): number {
342+
if (i < 0) {
343+
return 0;
344+
}
345+
if (f[i][j] !== -1) {
346+
return f[i][j];
347+
}
348+
349+
let left = arr[i][0] - arr[i][1];
350+
if (i > 0) left = Math.max(left, arr[i - 1][0] + 1);
351+
let l = _.sortedIndex(walls, left);
352+
let r = _.sortedIndex(walls, arr[i][0] + 1);
353+
let ans = dfs(i - 1, 0) + (r - l);
354+
355+
let right = arr[i][0] + arr[i][1];
356+
if (i + 1 < n) {
357+
if (j === 0) {
358+
right = Math.min(right, arr[i + 1][0] - arr[i + 1][1] - 1);
359+
} else {
360+
right = Math.min(right, arr[i + 1][0] - 1);
361+
}
362+
}
363+
l = _.sortedIndex(walls, arr[i][0]);
364+
r = _.sortedIndex(walls, right + 1);
365+
ans = Math.max(ans, dfs(i - 1, 1) + (r - l));
366+
367+
f[i][j] = ans;
368+
return ans;
369+
}
370+
371+
return dfs(n - 1, 1);
372+
}
130373
```
131374

132375
<!-- tabs:end -->

0 commit comments

Comments
 (0)