leetcode(28)BFS系列题目

2368. 受限条件下可到达节点的数目

步骤:
1.根据边建好无向图

[[1, 4, 5], [0, 2, 3], [1], [1], [0], [0, 6], [5]]
2.初始化访问过的节点visited里已经有受限节点了就不会再去访问,并且是set类型的,即不能重复访问
3.q里是当前能够到达的节点u,找到与u相连但是还没有访问(也没有被限制)的节点v

class Solution:
    def reachableNodes(self, n: int, edges: List[List[int]], restricted: List[int]) -> int:
        graph = [[] for _ in range(n)]
        for u, v in edges:
            graph[u].append(v)
            graph[v].append(u)

        print(graph)
        visited = set(restricted)
        visited.add(0)
        q = [0]
        res = 1
        while q:
            u = q.pop()
            for v in graph[u]:
                if v not in visited:
                    visited.add(v)
                    q.append(v)
                    res += 1
        return res

864. 获取所有钥匙的最短路径

没有进行状态压缩,state 记录当前收集过的钥匙

class Solution:
    def shortestPathAllKeys(self, grid: List[str]) -> int:
        keys, locks = 'abcdef', 'ABCDEF'
        cnt, res = 0, 0
        m, n = len(grid), len(grid[0])
        for i in range(m):
            for j in range(n):
                if grid[i][j] in keys:
                    cnt += 1
                if grid[i][j] == '@':
                    begin = (i, j)
        q = deque([(begin[0], begin[1], '')])
        vis = set()
        dire = [(-1,0),(1,0),(0,1),(0,-1)]
        while q:
            for _ in range(len(q)):
                i, j, state = q.popleft()  # 注意是left
                if (i, j, state) in vis:
                    continue
                if len(state) == cnt:
                    return res
                
                vis.add((i, j, state))
                for x, y in dire:
                    newi = i + x
                    newj = j + y
                    if not (0 <= newi < m and 0 <= newj < n and grid[newi][newj] != '#'):
                        continue  # 1.此路不通
                    if grid[newi][newj] in locks and grid[newi][newj].lower() in state:
                        q.append((newi, newj, state))  # 2.遇到锁但是有钥匙,可通
                    elif grid[newi][newj] in keys:   
                        if grid[newi][newj] in state:
                            q.append((newi, newj, state))  # 3.遇到收集过的钥匙
                        else:
                            q.append((newi, newj, state + grid[newi][newj]))  # 4.遇到没收集过的钥匙
                    elif grid[newi][newj] in '.@':  # 5.空房间可通
                        q.append((newi, newj, state))
            res += 1
        return -1
                    

815. 公交路线

class Solution:
    def numBusesToDestination(self, routes: List[List[int]], source: int, target: int) -> int:
        # 每个车站可以乘坐第几辆公交车
        stations = defaultdict(set)
        for i, stops in enumerate(routes):
            for stop in stops:
                stations[stop].add(i)
        # print(stations)

        # 每辆公交车可以到达哪些车站,转成set
        routes = [set(r) for r in routes]
        # print(routes)
        
        v_stop, v_bus = {source}, set()
        q = deque([(source, 0)])
        while q:
            cur, res = q.popleft()
            if cur == target: return res
            for bus in stations[cur] - v_bus:  # 在当前这个车站能坐哪些公交车
                for stop in routes[bus] - v_stop:  # 坐当前这个公交车能到哪些车站
                    v_bus.add(bus)
                    v_stop.add(stop)
                    q.append((stop, res + 1))
        return -1

参考资料:
BFS算法整理(python实现)
BFS算法解题套路框架(附习题)

posted @ 2022-08-09 16:19  YTT77  阅读(32)  评论(0编辑  收藏  举报