[BOJ] Q2666 벽장문의 이동

Question

Language: Python

Difficulty: Gold 5

특정 벽장 문을 열기 위해서는 닫혀 있는 문을 이동시켜야한다. 그러면, 열려 있는 두 문중에 하나를 선택해서 해당 문쪽으로 이동 시키는 작업을 진행해야한다.

그래서, 특정 문을 열기 위해, 열린 2개의 문에 대해 아래와 같은 점화식을 세워 볼 수 있다.

dp[next_door][door1][door2]=min(
        abs(next_door-door1) + dfs(count+1,next_door,door2),
        abs(next_door-door2) + dfs(count+1,door1,next_door)
    )

특정 문을 열기 위해, 열려 있는 문들 중에서, 거리값을 비교해서 초기화해준다.

해당 문제의 유형은 dfs 와 dp를 응용한 dfs+dp 응용 문제이다.

Solution 1

from math import inf
def dfs(count,door1,door2):
    global dp
    if count == n_movements:
        return 0

    next_door=movements[count]

    dp[next_door][door1][door2]=min(
        abs(next_door-door1) + dfs(count+1,next_door,door2),
        abs(next_door-door2) + dfs(count+1,door1,next_door)
    )

    return dp[next_door][door1][door2]  
if __name__ == "__main__":
    n_doors=int(input())
    door1,door2=map(int,input().split())
    n_movements=int(input())
    movements=[]
    for _ in range(n_movements):
        movements.append(int(input()))

    dp=[[[0] *(n_doors+1) for _ in range(n_doors+1)]for _ in range(n_doors+1)]
    print(dfs(0,door1,door2))

사실 해당 문제는 n의 크기가 매우 작으므로, 단순 dfs을 통하 bruteforce 방식을 취해도 풀이가 가능하다.

Solution 2

from math import inf
def dfs(cnt,door1,door2,move_count):
    global min_result
    if cnt==n_movements:
        min_result=min(min_result,move_count)
        return
    next_door=movements[cnt]
    dfs(cnt+1, next_door,door2,move_count+abs(next_door-door1))
    dfs(cnt+1, door1,next_door,move_count+abs(next_door-door2))
    
if __name__ == "__main__":
    n_doors=int(input())
    door1,door2=map(int,input().split())
    n_movements=int(input())
    movements=[]
    for _ in range(n_movements):
        movements.append(int(input()))

    min_result=inf
    dfs(0,door1,door2,0)
    print(min_result)

댓글남기기