📦11049: 행렬 곱셈 순서
[알고리즘 풀이] 강동규
Reviewed by midade midang (devmidade12@gmail.com)
Reviewed:: 2024-02-19
문제 확인하기
풀이
-
이 문제는 1시간을 고민해도 전혀 갈피를 잡지 못하겠어서 결국 https://cocoon1787.tistory.com/318의 풀이를 참고했다. 확실히 DP 문제에 약하다고 느껴진다.
-
dp[n][m] 는 n 에서 m 까지의 범위를 행렬 연산했음을 의미한다.
-
3중 for 문을 사용하여 행렬 연산의 범위, 시작 지점, 범위 연산을 지정해 계산한다.
-
i 는 행렬의 범위를 지정한다. i = 2 일 경우, dp[n][m] 에서 m-n, n과 m 사이의 거리, 차이가 2라는 뜻이다.
-
j 는 행렬의 시작 지점을 말한다. j = 3, i = 2 인 경우 dp[3][5] 로 3에서 시작해서 5번째까지의 행렬을 구한다.
-
mid 는 범위 안에서의 실질적인 연산을 진행한다. dp[3][10] 을 구한다고 하면 mid 는 3~10 의 값이고, 반복문을 돌면서 dp[3][3], dp[3][4], … 를 구한다.
-
최종적으로는 dp[1][N] 을 구하면 1~N 까지의 행렬 연산의 최솟값을 구할 수 있다.
-
혼자 생각할 때 dp로 느낌이 들기는 했지만 어떻게 풀어야 할지 감이 오지 않았다. 해당 문제를 풀이하는 방식이 이해를 하니까 끄덕일 수 있었지만 체득이 필요할 것 같다.
코드
#include <iostream>
#define endl '\n'
using namespace std;
int N;
int matInfo[501][2];
int dp[501][501];
void Input(){
cin >> N;
for(int i=1; i<=N; i++) {
cin >> matInfo[i][0] >> matInfo[i][1];
}
}
void Solution(){
for(int i=1; i<N; i++){
for(int j=1; i+j<=N; j++){
dp[j][i+j] = INT32_MAX;
for(int mid=j; mid<=i+j; mid++){
dp[j][i+j] = min(dp[j][i+j], dp[j][mid] + dp[mid+1][i+j] + matInfo[j][0]*matInfo[mid][1]*matInfo[i+j][1]);
}
}
}
cout << dp[1][N] << endl;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
Input();
Solution();
return 0;
}