알고리즘/BOJ - Java

[BOJ/Java] 11049. 행렬 곱셈 순서

ImJay 2025. 3. 10. 09:36
반응형

📌 [BOJ/Java] 11049. 행렬 곱셈 순서

🔗 문제 링크: 백준 11049번 - 행렬 곱셈 순서


📖 문제 해석

📌 N개의 행렬이 주어질 때, 모든 행렬을 곱하는 최소 연산 횟수를 구하는 문제이다.
💰 행렬 곱셈 연산 횟수는 A(p×q) × B(q×r) = p × q × r로 계산된다.
🛠️ 행렬을 곱하는 순서에 따라 연산 횟수가 달라지므로 최적의 곱셈 순서를 찾아야 한다.

🎯 핵심 개념

  • dp[i][j] = i번째 행렬부터 j번째 행렬까지 곱하는 최소 연산 횟수
  • dp[i][j] = min(dp[i][k] + dp[k+1][j] + cost(A[i] ~ A[k], A[k+1] ~ A[j]))
    (i부터 j까지 곱하는 최적의 k를 찾는다.)

🛠️ 풀이 과정

1️⃣ 입력 처리 및 초기화

  • 행렬 개수 N을 입력받고, 각 행렬의 (행, 열) 크기를 저장한다.
  • dp[i][j] 테이블을 생성하고, 대각선(dp[i][i])을 0으로 초기화한다.

2️⃣ DP 테이블 채우기

  • 부분 행렬 크기(2개 이상)부터 점진적으로 증가시키며 dp[i][j] 값을 갱신한다.
  • dp[i][j] = min(dp[i][k] + dp[k+1][j] + cost) 를 통해 최적의 k를 찾는다.

3️⃣ 최소 연산 횟수 찾기

  • dp[1][N]이 전체 행렬을 곱하는 최소 연산 횟수가 된다.

💻 코드 구현 (Java)

import java.util.*;

public class Main {
    static int[][] dp;
    static int[][] matrix;
    static int N;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        N = sc.nextInt();
        matrix = new int[N + 1][2]; // 행렬 크기 저장
        dp = new int[N + 1][N + 1];

        for (int i = 1; i <= N; i++) {
            matrix[i][0] = sc.nextInt(); // 행 크기
            matrix[i][1] = sc.nextInt(); // 열 크기
        }

        System.out.println(matrixChainOrder());
    }

    public static int matrixChainOrder() {
        for (int len = 2; len <= N; len++) { // 부분 행렬 길이 (2개 이상)
            for (int i = 1; i + len - 1 <= N; i++) { // 시작 인덱스
                int j = i + len - 1; // 끝 인덱스
                dp[i][j] = Integer.MAX_VALUE;

                for (int k = i; k < j; k++) { // 중간 지점 k
                    int cost = dp[i][k] + dp[k + 1][j] + (matrix[i][0] * matrix[k][1] * matrix[j][1]);
                    dp[i][j] = Math.min(dp[i][j], cost);
                }
            }
        }

        return dp[1][N]; // 전체 행렬을 곱하는 최소 연산 횟수
    }
}

⏱️ 시간 복잡도 분석

📌 O(N³) (최대 500³ = 약 1억 2500만 연산)
💡 dp[i][j]를 구하기 위해 중간 지점 k를 탐색해야 하므로 **O(N²) × O(N) = O(N³)**의 시간 복잡도를 가진다.
🔥 다행히 N ≤ 500이므로 DP를 사용하여 충분히 해결 가능하다.


💡 느낀점

최적의 행렬 곱셈 순서를 찾는 DP 문제로,
단순히 차례로 곱하는 것이 아닌 부분 문제를 정의하고 최적의 순서를 찾는 것이 중요했다.

행렬 곱셈 연산 횟수를 구할 때, 행렬 크기를 고려하는 것이 핵심이었다.

파일 합치기(11066) 문제와 유사한 방식으로 해결할 수 있었다! 🚀

반응형