문제 링크 : 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 |