1. 解题思路
这一题思路上就是一个动态规划+分类讨论的思路。
我们首先将所有的机器人以及墙壁位置顺序排列,然后从左往右依次考察每一个机器人向左以及向右射出子弹时其所能到达的范围,然后通过二分查找的方式去查找对应范围内的墙壁个数即可。
因此,我们只需要设计一个迭代函数dp(idx, dir),前者表示当前考察的机器人,后者表示前一个机器人的子弹射出方向,由此我们即可在
O
(
2
N
)
O(2N)
O(2N)的复杂度内将结果计算完毕。
但是需要注意的是,在实际计算子弹射出范围的时候,我们需要考察每一种情况下的子弹范围交叠情况,然后需要扣除掉多余的部分,这个还是需要分类讨论好好细化一下的,这里就不过多赘述了,有兴趣的读者对着代码自己想一下就行了。
2. 代码实现
给出python代码实现如下:
class Solution:
def maxWalls(self, robots: List[int], distance: List[int], walls: List[int]) -> int:
robs = sorted([(i, d) for i, d in zip(robots, distance)])
walls = sorted(walls)
n, m = len(robs), len(walls)
@lru_cache(None)
def dp(idx, ori):
if idx >= n:
return 0
loc, dis = robs[idx]
rbound = min(loc + dis, robs[idx+1][0]) if idx < n-1 else loc + dis
rcount = bisect_left(walls, rbound+1) - bisect_left(walls, loc)
lbound = max(loc - dis, robs[idx-1][0]) if idx > 0 else loc - dis
lcount = bisect_left(walls, loc+1) - bisect_left(walls, lbound)
if ori == "right":
if robs[idx-1][0] + robs[idx-1][1] >= loc:
wid = bisect.bisect_left(walls, loc)
if wid < m and walls[wid] == loc:
return rcount + dp(idx+1, "right") - 1
else:
return rcount + dp(idx+1, "right")
elif robs[idx-1][0] + robs[idx-1][1] >= lbound:
_lbound = min(robs[idx-1][0] + robs[idx-1][1]+1, loc+1)
_lcount = bisect_left(walls, loc+1) - bisect_left(walls, _lbound)
return max(rcount + dp(idx+1, "right"), _lcount + dp(idx+1, "left"))
else:
return max(rcount + dp(idx+1, "right"), lcount + dp(idx+1, "left"))
else:
if ori == "left" and lbound == robs[idx-1][0]:
wid = bisect.bisect_left(walls, lbound)
if wid < m and walls[wid] == lbound:
return max(rcount + dp(idx+1, "right"), lcount + dp(idx+1, "left")-1)
return max(rcount + dp(idx+1, "right"), lcount + dp(idx+1, "left"))
return dp(0, "")
提交代码评测得到:耗时1933ms,占用内存304.63MB。

被折叠的 条评论
为什么被折叠?



