목차

미로 탈출

ps
링크programmers.co.kr/…
출처프로그래머스
문제 번호81304
문제명미로 탈출
레벨Level 4
분류

다익스트라

시간복잡도O(E*T*2^T*logV)
인풋사이즈V<=1000, E<=3000, T<=10
사용한 언어Python
해결날짜2021/07/10
출처

ps:problems:programmers:2021_카카오_채용연계형_인턴십

풀이

코드

"""Solution code for "Programmers 81304. 미로 탈출".

- Problem link: https://programmers.co.kr/learn/courses/30/lessons/81304
- Solution link: http://www.teferi.net/ps/problems/programmers/81304
"""

import heapq

INF = float('inf')


def dijkstra(next_states_and_dists,
             source: int,
             is_sink_state) -> float:
    distances = {source: 0}
    heap = [(0, source)]
    while heap:
        dist_u, u = heapq.heappop(heap)
        if dist_u != distances[u]:
            continue
        if is_sink_state(u):
            return dist_u
        for v, dist_uv in next_states_and_dists(u):
            dist_v = dist_u + dist_uv
            if dist_v < distances.get(v, INF):
                distances[v] = dist_v
                heapq.heappush(heap, (dist_v, v))
    raise ValueError


def solution(n, start, end, roads, traps):
    def is_trap_activated(trap_state, node):
        return node in trap_bit and (trap_state & trap_bit[node]) != 0

    def flip_trap(trap_state, node):
        return (trap_state ^ trap_bit[node]) if node in trap_bit else trap_state

    def next_states_and_dists(state):
        u, trap_state = state
        is_cur_node_activated = is_trap_activated(trap_state, u)
        for v, dist in edges_from[u]:
            if is_cur_node_activated == is_trap_activated(trap_state, v):
                yield (v, flip_trap(trap_state, v)), dist
        for v, dist in edges_to[u]:
            if is_cur_node_activated != is_trap_activated(trap_state, v):
                yield (v, flip_trap(trap_state, v)), dist

    trap_bit = {trap - 1: (1 << i) for i, trap in enumerate(traps)}                
    edges_from = [[] for _ in range(n)]
    edges_to = [[] for _ in range(n)]    
    for u, v, dist in roads:
        edges_from[u - 1].append((v - 1, dist))
        edges_to[v - 1].append((u - 1, dist))

    return dijkstra(next_states_and_dists,
                    (start - 1, 0),
                    lambda state: state[0] == end - 1)