返回
LeetCode 1263. Minimum Moves to Move a Box to Their Target Location(Python)使用 BFS 思想解题
后端
2024-01-09 03:45:33
题目
给你一个大小为 m x n
的网格,其中包含箱子、墙壁和目标位置。箱子可以水平或垂直移动。
箱子不能穿过墙壁。
目标位置是箱子需要到达的最终位置。
从起始位置开始,返回将箱子移动到目标位置所需的 最少 移动次数。
如果箱子无法到达目标位置,返回 -1。
示例
示例 1:
输入:grid = [[0, 0, 0],
[0, 1, 0],
[0, 0, 0]]
起点:start = [0, 0]
目标:target = [2, 2]
输出:5
解释:箱子需要向右移动一次,向上移动两次,向右移动一次,然后向下移动两次。
示例 2:
输入:grid = [[0, 0, 0, 0, 0],
[1, 1, 1, 0, 1],
[0, 0, 0, 0, 0],
[0, 1, 0, 0, 1],
[0, 1, 0, 0, 0]]
起点:start = [4, 3]
目标:target = [3, 0]
输出:11
解释:首先,箱子需要向上移动一次,然后向右移动三次。然后,箱子需要向右移动两次,向上移动一次,向右移动一次,向上移动一次,向右移动一次,然后向上移动一次。最后,箱子需要向左移动一次,到达目标位置。
示例 3:
输入:grid = [[0, 0, 0],
[1, 0, 0],
[0, 0, 0]]
起点:start = [0, 0]
目标:target = [2, 0]
输出:-1
解释:箱子无法到达目标位置。
解题思路
我们可以使用广度优先搜索 (BFS) 来解决这个问题。
BFS 是从起始位置开始,然后向各个方向扩展。如果箱子能够移动到目标位置,则返回移动的总次数。否则,继续 BFS,直到找到目标位置。
为了实现 BFS,我们可以使用队列。我们将起始位置加入队列中,然后从队列中取出一个位置,并尝试向各个方向移动箱子。如果箱子能够移动到目标位置,则返回移动的总次数。否则,将新的位置加入队列中,并继续 BFS。
需要注意的是,我们需要使用 visited 数组来记录已经访问过的位置。这样,我们可以避免重复访问同一个位置。
Python 代码
from collections import deque
def min_moves_to_target(grid, start, target):
"""
计算将箱子移动到目标位置所需的最小移动次数。
参数:
grid: 一个大小为 m x n 的网格,其中包含箱子、墙壁和目标位置。
start: 箱子的起始位置。
target: 箱子的目标位置。
返回:
将箱子移动到目标位置所需的最小移动次数。如果箱子无法到达目标位置,返回 -1。
"""
# 检查网格是否有效
if not grid or not start or not target:
return -1
# 创建一个队列来存储要访问的位置
queue = deque([start])
# 创建一个 visited 数组来记录已经访问过的位置
visited = set()
visited.add(start)
# BFS
min_moves = 0
while queue:
# 从队列中取出一个位置
current_position = queue.popleft()
# 检查箱子是否已经到达目标位置
if current_position == target:
return min_moves
# 尝试向各个方向移动箱子
for dx, dy in [(1, 0), (-1, 0), (0, 1), (0, -1)]:
# 计算箱子移动后的位置
next_position = (current_position[0] + dx, current_position[1] + dy)
# 检查箱子是否能够移动到下一个位置
if next_position[0] < 0 or next_position[0] >= len(grid) or next_position[1] < 0 or next_position[1] >= len(grid[0]) or grid[next_position[0]][next_position[1]] == 1 or next_position in visited:
continue
# 将箱子移动到下一个位置
queue.append(next_position)
# 将下一个位置标记为已访问
visited.add(next_position)
# 增加移动次数
min_moves += 1
# 如果箱子无法到达目标位置,返回 -1
return -1
if __name__ == "__main__":
# 测试用例 1
grid1 = [[0, 0, 0],
[0, 1, 0],
[0, 0, 0]]
start1 = [0, 0]
target1 = [2, 2]
print(min_moves_to_target(grid1, start1, target1)) # 5
# 测试用例 2
grid2 = [[0, 0, 0, 0, 0],
[1, 1, 1, 0, 1],
[0, 0, 0, 0, 0],
[0, 1, 0, 0, 1],
[0, 1, 0, 0, 0]]
start2 = [4, 3]
target2 = [3, 0]
print(min_moves_to_target(grid2, start2, target2)) # 11
# 测试用例 3
grid3 = [[0, 0, 0],
[1, 0, 0],
[0, 0, 0]]
start3 = [0, 0]
target3 = [2, 0]
print(min_moves_to_target(grid3, start3, target3)) # -1
复杂度分析
- 时间复杂度:O(mn),其中 m 和 n 分别是网格的行数和列数。
- 空间复杂度:O(mn),其中 m 和 n 分别是网格的行数和列数。