행렬의 곱셈을 수행할 때에는 특별한 법칙이 있다.
곱하고자 하는 앞 행렬의 Column 수와 뒷 행렬의 Row 수가 일치해야 하며, 계산 결과로 앞 행렬의 Row X 뒷 행렬의 Column 크기를 갖는 행렬 결과가 나타난다.
그렇기 때문에 여러 개의 행렬을 곱할 때, 행렬의 곱셈 순서에 따라 곱셈 연산의 순서가 달라진다.
앞 행렬의 Column 과 뒷 행렬의 Row 가 넓은 범위에서 공통될 수록 연산의 비용이 커지게 된다.
행렬의 곱셈은 CS에서도 많이 사용되는 연산이기 때문에 이 문제는 알고리즘적으로도 유명한 행렬 곱셈(Matrix Multiplication) 문제이다.
이 문제의 일반적인 솔루션은 DP를 이용한 방식으로 O(n^3) 만큼의 시간복잡도와 O(n^2)의 공간복잡도를 갖는다.
간단하고 직관적이므로 DP를 입문할 때 대표적인 예제로 많이 언급된다.
각각 r[i]개의 행(row)과 c[i]개의 열(column) 을 가진 행렬 n개를 순차적으로 곱셈한다고 가정해보자.
여기서 순차적이라 함은 가령 (AB)C 와 A(BC) 처럼 A, B, C 행렬 3개의 곱의 순서가 보장되어야 한다는 것이다.
이 때 알고리즘은 다음과 같다.
(정의)
dp[i][j] => 행렬i부터 행렬j 까지를 곱할 때 필요한 곱셈의 최소횟수
dp[i][j] = dp[i][k] + dp[k+1][j] + 곱셈 비용 의 최솟값.
간단히 설명하면 구간 i ~ j까지 행렬곱셈을 수행시, i~k 까지의 행렬곱셈 X k+1~j 까지의 행렬곱셈 을 순차적으로 수행하는데 추가로 k~k+1 두 곱셈 결과 행렬의 연산 비용을 추가해주는 것이다.
다음 예제와 해답 코드로 공부해보도록 하자.
예제 : https://www.acmicpc.net/problem/11049
Matrix Multiplication 알고리즘은 Strassen Algorithm 을 통해 O(n^2)에 가깝게 튜닝이 가능하다.
다소 수학적인 이해가 필요하므로 다음 링크를 참조한다.
(https://en.wikipedia.org/wiki/Matrix_multiplication)
'DataStructure & Algorithm > Algorithm' 카테고리의 다른 글
알고리즘 풀이 시 자주 사용되는 bit 연산 모음 (0) | 2019.05.11 |
---|---|
최대공약수(GCD)와 최소공배수(LCM) 를 위한 유클리드 알고리즘 (0) | 2019.05.05 |
2차원 배열에서 Binary Search 적용하기 (0) | 2018.12.09 |
nLogn 보다 빠른 시간 복잡도로 정렬이 가능한 Counting Sort 정리 (0) | 2018.11.27 |
최적화된 LIS(Longest Increasing Subsequence) 알고리즘과 해 찾기 (0) | 2018.09.06 |