알고리즘/BOJ

[BOJ] 11049. 행렬 곱셈 순서

재담 2022. 3. 18. 02:37

문제 원본 : https://www.acmicpc.net/problem/11049

 

11049번: 행렬 곱셈 순서

첫째 줄에 입력으로 주어진 행렬을 곱하는데 필요한 곱셈 연산의 최솟값을 출력한다. 정답은 231-1 보다 작거나 같은 자연수이다. 또한, 최악의 순서로 연산해도 연산 횟수가 231-1보다 작거나 같

www.acmicpc.net

import java.io.*;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int n = Integer.parseInt(br.readLine());
        int[][] mat = new int[n][2];
        int[][] dp = new int[n][n];
        int[][][] mem = new int[n][n][2];

        StringTokenizer st = null;
        for (int i = 0; i < n; ++i) {
            st = new StringTokenizer(br.readLine());
            mat[i][0] = Integer.parseInt(st.nextToken());
            mat[i][1] = Integer.parseInt(st.nextToken());
            mem[i][i][0] = mat[i][0];
            mem[i][i][1] = mat[i][1];
        }

        for (int i = 0; i < n - 1; ++i) {
            dp[i][i + 1] = mat[i][0] * mat[i][1] * mat[i + 1][1];
            mem[i][i + 1][0] = mat[i][0];
            mem[i][i + 1][1] = mat[i + 1][1];
        }

        for (int i = 0; i < n - 2; ++i) {
            for (int j = 0; i + j + 2 < n; ++j) {
                int l = i + j + 2;
                dp[j][l] = Integer.MAX_VALUE;

                for (int k = j; k < l; ++k) {
                    dp[j][l] = Math.min(dp[j][l], mem[j][k][0] * mem[j][k][1] * mem[k + 1][l][1] + dp[j][k] + dp[k + 1][l]);
                }

                mem[j][l][0] = mat[j][0];
                mem[j][l][1] = mat[l][1];
            }
        }

        bw.write(String.valueOf(dp[0][n - 1]));

        bw.close();
        br.close();
    }
}
  • 다이내믹 프로그래밍 문제
  • 파일 합치기 문제와 비슷한 문제이다.
  • 중간에 만들어지는 행렬의 행과 열의 값을 mem 배열에 저장해가면서 풀었다.