본문 바로가기

프로그래밍/Python

[백준] 11049번 - 행렬 곱셈 순서

문제 링크 : https://www.acmicpc.net/problem/11049

 

문제

크기가 N×M인 행렬 A와 M×K인 B를 곱할 때 필요한 곱셈 연산의 수는 총 N×M×K번이다. 행렬 N개를 곱하는데 필요한 곱셈 연산의 수는 행렬을 곱하는 순서에 따라 달라지게 된다.

예를 들어, A의 크기가 5×3이고, B의 크기가 3×2, C의 크기가 2×6인 경우에 행렬의 곱 ABC를 구하는 경우를 생각해보자.

  • AB를 먼저 곱하고 C를 곱하는 경우 (AB)C에 필요한 곱셈 연산의 수는 5×3×2 + 5×2×6 = 30 + 60 = 90번이다.
  • BC를 먼저 곱하고 A를 곱하는 경우 A(BC)에 필요한 곱셈 연산의 수는 3×2×6 + 5×3×6 = 36 + 90 = 126번이다.

같은 곱셈이지만, 곱셈을 하는 순서에 따라서 곱셈 연산의 수가 달라진다.

행렬 N개의 크기가 주어졌을 때, 모든 행렬을 곱하는데 필요한 곱셈 연산 횟수의 최솟값을 구하는 프로그램을 작성하시오. 입력으로 주어진 행렬의 순서를 바꾸면 안 된다.

 

입력

첫째 줄에 행렬의 개수 N(1 ≤ N ≤ 500)이 주어진다.

둘째 줄부터 N개 줄에는 행렬의 크기 r과 c가 주어진다. (1 ≤ r, c ≤ 500)

항상 순서대로 곱셈을 할 수 있는 크기만 입력으로 주어진다.

 

출력

첫째 줄에 입력으로 주어진 행렬을 곱하는데 필요한 곱셈 연산의 최솟값을 출력한다. 정답은 231-1 보다 작거나 같은 자연수이다. 또한, 최악의 순서로 연산해도 연산 횟수가 231-1보다 작거나 같다.

 

풀이

import sys
input = sys.stdin.readline

N = int(input())
mat = [[]]
D = [[-1 for _ in range(N+1)] for _ in range(N+1)]

for _ in range(N):
    mat.append(list(map(int, input().split())))

def dp(s, e):
    result = sys.maxsize
    if D[s][e] != -1:
        return D[s][e]
    if s == e:
        return 0
    if s + 1 == e:
        return mat[s][0]*mat[s][1]*mat[e][1]
    for i in range(s, e):
        result = min(result, mat[s][0]*mat[i][1]*mat[e][1] + dp(s, i) + dp(i+1, e))
    D[s][e] = result
    return D[s][e]

print(dp(1,N))

 

해설

  • 어떤 두 행렬이 합쳐지기 위해서는 각 두 행렬이 합쳐지기까지의 값들을 더하고 둘을 합칠 때 필요한 연산의 수를 구해 더한다.
  • sys.maxsize는 최댓값을 초기화할 때 유용하다. 최솟값을 초기화할 때는 -sys.maxsize로 사용하면 된다.

'프로그래밍 > Python' 카테고리의 다른 글

[백준] 13398번 - 연속합 2  (0) 2025.03.05
[백준] 1256번 - 사전  (0) 2025.03.05
[백준] 1722번 - 순열의 순서  (0) 2025.03.01
[백준] 1717번 - 집합의 표현  (0) 2025.02.20
[백준] 1850번 - 최대공약수  (0) 2025.02.19