N(1≤N≤500) 개의 행렬이 주어졌을 때 어떤 순서로 곱셈을 해야 연산 횟수를 최소화할 수 있을까?
예를 들어 A가 5x3이고 B가 3x2, C가 2x6인 경우를 생각해보자.
우선 (AB) C는 5x2 AB를 만들기 위해 5x3x2의 연산 횟수가 필요하고 5x2 AB와 2x6C가 곱해져 최종적으로 5x6이 나오는데 여기에 5x2x6의 연산 횟수가 필요하다.
최종적으로 5x3x2 + 5x2x6 = 90번의 연산이다.
그런데 이 연산을 A(BC)로 하면 3x2x6 + 5x3x6 = 126이 된다. 같은 곱셈이지만 곱셈 연산 수가 다르다.
우선 완전 탐색을 고려할 수 있다. 하지만 너무 많다..
생각해 보면 ABCD가 있을 때 (AB)(CD)가 있을 수 있고 ((AB) C) D가 있을 수 있다. AB가 반복해서 나온다. 즉 DP를 사용하면 될 것 같다.
상태를 생각해 보자. i 번째까지의 최소 연산 횟수를 저장하면 될까?
아니다. 앞에서부터 계산한다고 결과가 최소가 되지 않는다.
i부터 j까지의 연산을 기록하자..
그렇다면 dp[i][j]를 어떻게 정의할까?
dp[i][j]: i 번째 행렬부터 j번째 행렬까지 곱하는데 필요한 최소 연산 횟수
dp[i][j] = min(dp[i][k] + dp[k+1][j] + (i x k x j))가 된다.
package boj;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class BOJ11049 {
static FastReader scan = new FastReader();
static int N;
static int[][] matrices;
static void input() {
N = scan.nextInt();
matrices = new int[N][2];
for (int i = 0; i < N; i++) {
matrices[i] = new int[]{scan.nextInt(), scan.nextInt()};
}
}
static void solve() {
int[][] dp = new int[N][N];
for (int i = 0; i < N; i++) {
Arrays.fill(dp[i], -1);
}
System.out.println(recFunc(0, N - 1, dp));
}
static int recFunc(int start, int end, int[][] dp) {
if (start == end) {
return 0;
}
if (dp[start][end] != -1) {
return dp[start][end];
}
dp[start][end] = Integer.MAX_VALUE;
for (int mid = start; mid < end; mid++) {
int leftCost = recFunc(start, mid, dp);
int rightCost = recFunc(mid + 1, end, dp);
int mergeCost = matrices[start][0] * matrices[mid][1] * matrices[end][1];
dp[start][end] = Math.min(dp[start][end], leftCost + rightCost + mergeCost);
}
return dp[start][end];
}
public static void main(String[] args) {
input();
solve();
}
static class FastReader {
BufferedReader br;
StringTokenizer st;
public FastReader() {
br = new BufferedReader(new InputStreamReader(System.in));
}
String next() {
while (st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
}
}
'Algorithm > BOJ' 카테고리의 다른 글
BOJ 6087 - 레이저 통신 (0) | 2024.11.07 |
---|---|
BOJ 10021 - Watering the Fields (0) | 2024.11.06 |
BOJ 2292 - 벌집 (5) | 2024.11.06 |
BOJ 2933 - 미네랄 (0) | 2024.11.05 |
BOJ 15591 - MooTube (Silver) (0) | 2024.10.31 |