문제
출처 : https://www.acmicpc.net/problem/11049
N개의 행렬이 주어진다.
행렬 A의 크기를 N*M, 행렬 B의 크기를 M*K라고 할때,
각 행렬을 곱할때 필요한 곱셈 연산 수는 N*M*K이다.
모든 행렬을 곱하는데 필요한 최소 연산횟수를 구하는 문제다.
풀이
다이나믹 프로그래밍으로 풀리는 문제다.
처음엔 그리디로 생각했지만, 현재 최적값이 나중에도 최적이라는 보장이없기때문에 그리디로는 풀기 힘들어보인다.
이 문제처럼 dp식이 한번에 떠오르지 않거나, 헷갈린다면, 모든 경우를 나열해보면 도움이 된다.
배열이 5개있고, 각 배열에 1번부터 5번까지 마크가 되어있다고 하자.
각 배열을 곱하는 순서는 다음과 같이 나올수있다.
((((12)3)4)5)
(((12)3)(45))
.
.
.
(1(2(3(45))))
(12)(3(45))
((1(23))(45))
중복되는 부분이 보이므로 최적화를 시켜줄수있다.
나올수있는 모든 경우가 최대 N^2이므로, 중복되는 부분을 최적화시켜주면, 약 O(N^2)의 시간복잡도로 해결이 가능한 문제였다.
dp코드
private Array getDp(int left, int right){
if(dp[left][right] != null) return dp[left][right];
if(left - right == 1 || left - right == -1)
return dp[left][right] = calcArray(arr[left], arr[right]);
Array ansArray = new Array(INF, INF, INF);
for(int i = 1; i < right-left; i++)
ansArray = getMin(ansArray, getMin(
calcArray(dp[left][left+(i-1)], getDp(left+i, right)),
calcArray(getDp(left, right-i),dp[right-(i-1)][right])
));
return dp[left][right] = ansArray;
}
전체 소스코드
'알고리즘 (2020 : 08 : 10 ~ ) > 다이나믹 프로그래밍' 카테고리의 다른 글
[백준 / BOJ] 2533 사회망 서비스(SNS) (0) | 2021.10.22 |
---|---|
[백준 / BOJ] 20925 메이플스토리 (0) | 2021.07.15 |
[백준 / BOJ] 1099 알 수 없는 문장 (Java) (3) | 2021.06.15 |
[백준/BOJ] 9625 BABBA (Java) (0) | 2021.06.14 |
[백준 / BOJ] 1949 우수 마을 (Java) (0) | 2021.05.30 |