본문 바로가기

두두의 알고리즘/문제

[동적계획법] 난이도1.5, Flipkart 인터뷰 '금광' (Python)

728x90

<문제>

n x m 크기의 금광이 있습니다. 금광은 1 x 1 크기의 칸으로 나누어져 있으며, 각 칸은 특정한 크기의 금이 들어 있습니다. 채굴자는 첫 번째 열부터 출발하여 금을 캐기 시작합니다. 맨 처음에는 첫 번째 열의 어느 행에서든 출발할 수 있습니다. 이후에 m번에 걸쳐서 매번 오른쪽 위, 오른쪽, 오른쪽 아래 3가지 중 하나의 위치로 이동해야 합니다. 결과적으로 채굴자가 얻을 수 있는 금의 최대 크기를 출력하는 프로그램을 작성하세요.

만약 다음과 같이 3x4 크기의 금광이 존재한다고 가정합시다.
1 3 3 2
2 1 4 1
0 6 4 7

가장 왼쪽 위의 위치를 (1,1), 가장 오른쪽 아래의 위치를 (n, m)이라고 할 때, 위 예시에서는 (2,1) -> (3,2) -> (3,3) -> (3,4)의 위치로 이동하면 총 19만큼의 금을 채굴할 수 있으며, 이때의 값이 최댓값입니다.

 

<입력 조건>

  • 첫째 줄에 테스트 케이스 T가 입력됩니다. (1 <= T <= 1000)
  • 매 테스트 케이스 첫째 줄에 n과 m이 공백으로 구분되어 입력됩니다. (1 <= n, m <= 20)
  • 둘째 줄에 n x m개의 위치에 매장된 금의 개수가 공백으로 구분되어 입력됩니다. (1 <= 각 위치에 매장된 금의 개수 <= 100)

<출력 조건>

  • 테스트 케이스마다 채굴자가 얻을 수 있는 금의 최대 크기를 출력합니다. 각 테스트 케이스는 줄 바꿈을 이용해 구분합니다.

<문제 풀이>

  1. 채굴자가 얻을 수 있는 금의 최대 크기를 구해야 하므로 max 함수 활용
  2. 테스트 케이스가 한 번에 여러 개 입력되므로 for문 안에서 알고리즘 실행
  3. 1열은 이전의 값이 없으므로 2열부터 시작함
  4. 예를 들어, 2열 1행은 1열 1행 또는 1열 2행의 값을 받을 수 있으므로 두 값 중 큰 수와 더해줌.
  5. 2열 마지막행은 1열 마지막행 또는 1열 마지막행-1의 값을 받을 수 있으므로 두 값 중 큰 수와 더해줌.
  6. 2열 중간행은 위,중간,아래행의 값을 받을 수 있으므로 세 값 중 큰 수와 더해줌.

<코드>

'''입력 예시
2
3 4
1 3 3 2 2 1 4 1 0 6 4 7
4 4
1 3 1 5 2 4 1 5 0 2 3 0 6 1 2
'''

t = int(input())

for i in range(t):
    n, m = map(int, input().split())
    graph = []
    inp = list(map(int, input().split()))
    for j in range(n):
        graph.append(inp[0 + (j * m):m + (j * m)])
    maxx = 0
    for y in range(1, m):
        for x in range(n):
            if x == 0:
                graph[x][y] += max(graph[x][y - 1], graph[x + 1][y - 1])
            elif x == n - 1:
                graph[x][y] += max(graph[x - 1][y - 1], graph[x][y - 1])
            else:
                graph[x][y] += max(graph[x][y - 1], graph[x - 1][y - 1], graph[x + 1][y - 1])
            if y == m - 1:
                if maxx < graph[x][y]:
                    maxx = graph[x][y]
    print(maxx)
#220324
t = int(input())

for i in range(t):
    gold = []
    n,m = map(int,input().split())
    tmp = list(map(int,input().split()))
    for i in range(n):
        gold.append(tmp[i*m:(i+1)*m])

    for y in range(m):
        if y==0:
            continue
        for x in range(n):

            if x==0:
                gold[x][y] += max(gold[x][y-1], gold[x+1][y-1])
            elif x==n-1:
                gold[x][y] += max(gold[x-1][y-1], gold[x][y-1])
            else:
                gold[x][y] += max(gold[x-1][y-1], gold[x][y-1], gold[x+1][y-1])
    answer = 0

    for i in range(n):
        if answer < gold[i][-1]:
            answer = gold[i][-1]
    print(answer)