[Gold III] Title: 행렬 곱셈 순서, Time: 824 ms, Memory: 113588 KB -BaekjoonHub

This commit is contained in:
SSUM
2026-02-09 20:41:42 +09:00
parent 334edc6fb1
commit dd02393381
2 changed files with 83 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
# [Gold III] 행렬 곱셈 순서 - 11049
[문제 링크](https://www.acmicpc.net/problem/11049)
### 성능 요약
메모리: 113588 KB, 시간: 824 ms
### 분류
다이나믹 프로그래밍
### 제출 일자
2026년 2월 9일 20:40:46
### 문제 설명
<p>크기가 N×M인 행렬 A와 M×K인 B를 곱할 때 필요한 곱셈 연산의 수는 총 N×M×K번이다. 행렬 N개를 곱하는데 필요한 곱셈 연산의 수는 행렬을 곱하는 순서에 따라 달라지게 된다.</p>
<p>예를 들어, A의 크기가 5×3이고, B의 크기가 3×2, C의 크기가 2×6인 경우에 행렬의 곱 ABC를 구하는 경우를 생각해보자.</p>
<ul>
<li>AB를 먼저 곱하고 C를 곱하는 경우 (AB)C에 필요한 곱셈 연산의 수는 5×3×2 + 5×2×6 = 30 + 60 = 90번이다.</li>
<li>BC를 먼저 곱하고 A를 곱하는 경우 A(BC)에 필요한 곱셈 연산의 수는 3×2×6 + 5×3×6 = 36 + 90 = 126번이다.</li>
</ul>
<p>같은 곱셈이지만, 곱셈을 하는 순서에 따라서 곱셈 연산의 수가 달라진다.</p>
<p>행렬 N개의 크기가 주어졌을 때, 모든 행렬을 곱하는데 필요한 곱셈 연산 횟수의 최솟값을 구하는 프로그램을 작성하시오. 입력으로 주어진 행렬의 순서를 바꾸면 안 된다.</p>
### 입력
<p>첫째 줄에 행렬의 개수 N(1 ≤ N ≤ 500)이 주어진다.</p>
<p>둘째 줄부터 N개 줄에는 행렬의 크기 r과 c가 주어진다. (1 ≤ r, c ≤ 500)</p>
<p>항상 순서대로 곱셈을 할 수 있는 크기만 입력으로 주어진다.</p>
### 출력
<p>첫째 줄에 입력으로 주어진 행렬을 곱하는데 필요한 곱셈 연산의 최솟값을 출력한다. 정답은 2<sup>31</sup>-1 보다 작거나 같은 자연수이다. 또한, 최악의 순서로 연산해도 연산 횟수가 2<sup>31</sup>-1보다 작거나 같다.</p>

View File

@@ -0,0 +1,40 @@
import sys
input = sys.stdin.readline
N = int(input())
M = [None] # 1-indexed를 위해 더미 삽입
for i in range(N):
r, c = map(int, input().split())
M.append((r, c))
# D[s][e]: 행렬 s~e를 곱하는 최소 연산 횟수 (-1이면 아직 미계산)
D = [[-1] * (N + 1) for _ in range(N + 1)]
def solve(s, e):
# 이미 계산했으면 바로 반환 (메모이제이션)
if D[s][e] != -1:
return D[s][e]
# Base Case 1: 행렬 1개 → 곱셈 불필요
if s == e:
return 0
# Base Case 2: 행렬 2개 → 바로 곱하기
if s + 1 == e:
D[s][e] = M[s][0] * M[s][1] * M[e][1]
return D[s][e]
# Recursive Case: 모든 분할 지점 k 시도
result = sys.maxsize
for k in range(s, e):
cost = (
solve(s, k) # 왼쪽 구간 비용
+ solve(k + 1, e) # 오른쪽 구간 비용
+ M[s][0] * M[k][1] * M[e][1] # 두 결과를 합치는 비용
)
result = min(result, cost)
D[s][e] = result
return result
print(solve(1, N))