LeetCode题解(LCP13):地图寻宝(Python)
发布日期:2021-06-29 20:15:29
浏览次数:3
分类:技术文章
本文共 4987 字,大约阅读时间需要 16 分钟。
题目:(困难)
标签:图、广度优先搜索、动态规划、深度优先搜索、记忆化递归
解法 | 时间复杂度 | 空间复杂度 | 执行用时 |
---|---|---|---|
Ans 1 (Python) | O ( N × M 2 + 2 N ) O(N×M^2+2^N) O(N×M2+2N) : 其中M为地图边长;N为机关数量 | O ( N 2 ) O(N^2) O(N2) | 7412ms (7.69%) |
Ans 2 (Python) | |||
Ans 3 (Python) |
解法一:
class Solution: def __init__(self): # 地图信息 self.maze = [] self.s1, self.s2 = 0, 0 # 地图内信息 self.gear = [] # 机关列表 self.stone = [] # 石碓列表 self.target = (-1, -1) # 目标位置 self.start = (-1, -1) # 起点 self.wall = set() # 墙 self.num1, self.num2 = 0, 0 # 机关数量、石碓数量 # 特殊点信息 self.special_list = [] self.special_dict = { } # 机关点距离关系 self.distance1 = [] self.distance2 = [] self.distance3 = [] def _is_valid(self, x, y): return 0 <= x < self.s1 and 0 <= y < self.s2 and (x, y) not in self.wall def _get_neighbour(self, x, y): return [(i, j) for (i, j) in [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)] if self._is_valid(i, j)] def _initialize(self): """初始化地图:初始化后支持在任意两个特殊点之间计算距离""" # 找到所有目标位置 for i in range(self.s1): for j in range(self.s2): if self.maze[i][j] == "S": self.start = (i, j) elif self.maze[i][j] == "T": self.target = (i, j) elif self.maze[i][j] == "O": self.stone.append((i, j)) elif self.maze[i][j] == "M": self.gear.append((i, j)) elif self.maze[i][j] == "#": self.wall.add((i, j)) # 计算机关数量和石碓数量 self.num1 = len(self.gear) self.num2 = len(self.stone) # 生成特殊点列表 self.special_list = [self.start] + self.stone + self.gear + [self.target] self.special_dict = { point: i for i, point in enumerate(self.special_list)} # 计算所有特殊点之间的距离 size = len(self.special_list) self.distance = [[float("inf")] * size for _ in range(size)] for i in range(size): point = self.special_list[i] # 生成目标列表 targets = { self.special_list[j]: j for j in range(i + 1, size)} # 广度优先搜索 queue = collections.deque([point]) visited = { point} step = 0 while queue: step += 1 for _ in range(len(queue)): (i1, j1) = queue.popleft() for (i2, j2) in self._get_neighbour(i1, j1): if (i2, j2) in targets: self.distance[i][targets[(i2, j2)]] = step self.distance[targets[(i2, j2)]][i] = step del targets[(i2, j2)] if (i2, j2) not in visited: queue.append((i2, j2)) visited.add((i2, j2)) if not targets: break def _get_distance(self, point1, point2): """计算两个特殊点之间的距离:默认两个点均为特殊点""" return self.distance[self.special_dict[point1]][self.special_dict[point2]] def minimalSteps(self, maze: List[str]) -> int: self.s1, self.s2 = len(maze), len(maze[0]) self.maze = maze # 初始化地图 self._initialize() # 处理没有机关的情况 if not self.gear: res = self._get_distance(self.start, self.target) return res if res != float("inf") else -1 # 计算从起点开始到达每个机关的距离(中间搬一次石头) self.distance1 = [float("inf")] * self.num1 for i in range(self.num1): for j in range(self.num2): res = self._get_distance(self.start, self.stone[j]) + self._get_distance(self.stone[j], self.gear[i]) self.distance1[i] = min(self.distance1[i], res) # 计算从每个机关到达另一个机关的距离(中间搬一次石头) self.distance2 = [[float("inf")] * self.num1 for _ in range(self.num1)] for i1 in range(self.num1): for i2 in range(i1 + 1, self.num1): for j in range(self.num2): res = (self._get_distance(self.gear[i1], self.stone[j]) + self._get_distance(self.stone[j], self.gear[i2])) self.distance2[i1][i2] = self.distance2[i2][i1] = min(self.distance2[i1][i2], res) # 计算从每个机关开始到达终点的距离 self.distance3 = [self._get_distance(self.gear[i], self.target) for i in range(self.num1)] # 记忆化递归计算最终结果 ans = min(self.dfs(i, (1 << i)) + self.distance1[i] for i in range(self.num1)) return ans if ans != float("inf") else -1 @functools.lru_cache(None) def dfs(self, now, state): """深度优先搜索(记忆化递归):now=当前所在机关位置;state=当前状态""" # 处理已经触发所有机关的情况 if state == (1 << len(self.gear)) - 1: return self.distance3[now] # 处理还没有触发所有机关的情况 res = float("inf") for i in range(self.num1): # 遍历所有可以移动的下一个机关 if state & (1 << i) == 0 and self.distance2[now][i] != float("inf"): res = min(res, self.dfs(i, state | (1 << i)) + self.distance2[now][i]) return res
转载地址:https://dataartist.blog.csdn.net/article/details/112571118 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月23日 19时08分49秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
DataTable,DataView和DataGrid中一些容易混淆的概念
2019-04-30
c#.net在WEB页中设置COOKIES
2019-04-30
Cookie使用基础
2019-04-30
C# cookie的使用
2019-04-30
C#如何创建、读取cookie
2019-04-30
Cookie在网站中的两大使用方法[cookie使用]
2019-04-30
C# 细说Cookie
2019-04-30
两个Cookie类
2019-04-30
C#中StringBuilder类的使用
2019-04-30
String,StringBuffer与StringBuilder的区别??
2019-04-30
用户登录安全性的简单实例分析(Cookie、加密)
2019-04-30
Cookie详解!
2019-04-30
Cookie/Session机制详解
2019-04-30
C# DES加密解密字符串
2019-04-30
C# 加密解密算法
2019-04-30
C#.NET 加密解密:AES/DES/Base64/RSA/MD5/SHA256
2019-04-30
C#修饰符
2019-04-30
C# 修饰符 总结
2019-04-30
C#修饰符
2019-04-30