[BAEKJOON][python] 백준 온라인 저지 문제 풀이 - 11909번: 배열 탈출

yohn·2024년 7월 17일
0

PS

목록 보기
5/9

문제 링크

문제
상수는 2차원 배열 A[1..n][1..n] (n≥2, n은 자연수)을 가지고 있습니다. 이 배열의 각 원소는 1 이상 222 이하의 정수입니다.
배열을 가지고 놀던 상수를 본 승현이는, 질투심이 불타올라 상수를 A[1][1]에 가둬 버렸습니다! 최소한의 양심이 있던 승현이는 A[n][n]에 출구를 만들어 놓고 이 사실을 상수에게 알려줬습니다.

[그림 1] n=4라면 상수는 A[1,1]에 있고, 출구는 A[4][4]에 있습니다.

상수는 가능한 한 빨리 출구인 A[n][n]에 도달하고자 합니다. 상수가 A[i][j]에 있다고 가정했을 때, 상수는 최단 경로로 이동하기 위해 아래와 같은 조건을 만족하며 이동합니다.
1≤i,j<n이라면, 상수는 A[i][j+1] 또는 A[i+1][j]로만 건너갑니다.
i=n,1≤j<n이라면, A[i][j+1]로만 건너갑니다.
1≤i<n,j=n이라면 A[i+1][j]로만 건너갑니다.
i=j=n인 경우 바로 출구로 갑니다.

[그림 2] n=5라고 가정합시다. (ㄱ)는 1번 조건을 만족하고, (ㄴ)는 2번 조건을 만족하며, (ㄷ)는 3번 조건을 만족합니다.

그러나 건너갈 때에도 제약이 따릅니다. 상수가 A[a][b]에서 A[c][d]로 건너가려면 A[a][b]>A[c][d]를 만족해야 합니다. 상수는 왜인지 이런 조건을 만족하면서 이동할 수 없을 것 같았습니다. 다행히도, 승현이가 상수를 배열에 가둬버리기 전에, 상수는 배열의 각 원소에 버튼을 만들어 놓아서, 이 버튼을 누르면 해당 원소의 값이 1 증가하도록 했습니다. (물론 상수는 자신이 위치해 있는 원소의 버튼만 누를 수 있습니다.) 이 버튼 덕분에, 상수는 항상 배열을 탈출할 수 있습니다!

[그림 3] n=2라고 가정합시다. A[1][1]=5>A[1][2]=2이므로, 상수는 A[1][1]에서 A[1][2]로 건너갈 수 있습니다. 상수가 A[1][1]에서 A[2][1]로 건너가려면, A[1][1]에 있는 버튼을 두 번 눌러 A[1][1]의 값을 7로 만들면 됩니다.

하지만 버튼을 한 번 누르는 데에는 1원의 비용이 듭니다. 상수는 돈을 가능한 한 적게 들이면서 배열을 탈출하고자 합니다. 상수를 도와주세요.

입력
첫 번째 줄에 n이 주어집니다. (n ≤ 2,222)

다음에 n개 줄이 주어집니다. 이 중 i(1≤i≤n)번째 줄에는 n개의 수 A[i][1],A[i][2],⋯,A[i][n−1],A[i][n]이 공백을 사이로 두고 차례대로 주어집니다.

출력
첫 번째 줄에 상수가 배열을 탈출하기 위해 들여야 할 최소 비용(원 단위)을 출력합니다.

소스코드

n = int(input())
graph = []
for _ in range(n):
    graph.append(list(map(int, input().split())))

cost = [[0] * n for _ in range(n)]

for j in range (1, n) : # graph[0][j] 초기화
    if graph[0][j - 1] > graph[0][j]:
        cost[0][j] = cost[0][j - 1]
    else:
        cost[0][j] = graph[0][j] - graph[0][j - 1] + 1 + cost[0][j - 1]

for i in range (1, n) : # graph[i][0] 초기화
    if graph[i - 1][0] > graph[i][0]:
        cost[i][0] = cost[i - 1][0]
    else:
        cost[i][0] = graph[i][0] - graph[i - 1][0] + 1 + cost[i - 1][0]

for i in range (1, n) : # graph[i][j] 초기화
    for j in range (1, n) :
        if graph[i - 1][j] > graph[i][j]:
            upCost = cost[i - 1][j]
        else:
            upCost = graph[i][j] - graph[i - 1][j] + 1 + cost[i - 1][j]
        if graph[i][j - 1] > graph[i][j]:
            leftCost = cost[i][j - 1]
        else:
            leftCost = graph[i][j] - graph[i][j - 1] + 1 + cost[i][j - 1]
        cost[i][j] = min(upCost, leftCost) # 위에서 아래로 내려올 때의 cost와 왼쪽에서 오른쪽으로 이동할 때의 cost 중 작은 것 저장
print(cost[n - 1][n - 1])

태그에는 데이크스트라, 최단 경로 등이 있지만.. 저는 경로를 구하기보다는 최소 cost를 구하는 것에 초점을 맞췄습니다.
[i][0]인 칸들과 [0][j]인 칸들은 각각 도달할 수 있는 방법이 한 가지(위에서 아래로 이동하는 방법, 왼쪽에서 오른쪽으로 이동하는 방법)입니다. 그리고 나머지 칸들은 위에서 아래로 이동하거나, 왼쪽에서 오른쪽으로 이동하여 도달할 수 있기 때문에 도달 방법이 두 가지 입니다.
그렇기 때문에 n×nn \times n 크기의 리스트를 하나 더 생성하고, [i][0]와 [0][j]칸들의 cost를 초기화합니다. 그리고 이 cost들을 이용하여 [i][j](i0,j0)(i \ne 0, j \ne 0)인 칸들의 최소 cost를 계산했습니다.

profile
공부하는 대학생

0개의 댓글

관련 채용 정보