ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [KOITP]Matrix Chain Multiplication
    자료구조 및 알고리즘/문제풀이 2016. 12. 12. 00:56

    출처 : http://www.koitp.org/problem/MATRIX_CHAIN_MULTIPLICATION/read/

    시간 제한메모리 제한제출 횟수정답 횟수 (비율)정답자 수
    1.0 초512 MB278106 (38%)95

    문제

    M×N 크기의 행렬 A와 N×K 크기의 행렬 B의 행렬 곱셈 AB를 생각해보자. 두 행렬의 곱셈 과정의 연산 횟수는 MNK 이다. 행렬 곱셈에는 교환 법칙 AB=BA는 성립하지 않지만, 결합 법칙 (AB)C=A(BC)는 성립한다. 결합 법칙에 의해 어떤 순서로 곱셈을 하는지에 따라 전체 연산 횟수가 차이난다.

    예를 들어, 세 행렬 A1,A2,A3가 있다고 하자. A1은 10×100 크기, A2는 100×5 크기, A3은 5×50 크기의 행렬이다. (A1A2)A3 순서로 곱셈을 할 경우, 전체10×100×5+10×5×50=7,500번의 연산이 필요하고, A1(A2A3) 순서로 곱셈할 경우, 전체 100×5×50+10×100×50=75,000번의 연산이 필요하다.

    n개의 행렬 A1,A2,A3,,An이 있다. 행렬 Ai의 크기는 ai×ai+1이다. 이 때, A1A2A3An을 계산하는데 필요한 연산의 최소 횟수를 구하는 프로그램을 작성하라.

    입력

    첫 줄에 행렬의 개수 n이 주어진다. (2n500)

    둘째 줄에 행렬의 크기를 나타내는 자연수 n+1개가 공백으로 구분되어 주어진다. i번째로 주어지는 수는 ai이다. (ai100)

    출력

    첫 줄에 A1A2A3An를 구하기 위해 필요한 연산의 최소 횟수를 출력한다.

    힌트

    예제 입력

    3
    10 100 5 50
    

    예제 출력

    7500


    < Comment >

     문제를 풀다가 몸이 조금 안 좋아, 평소보다는 빨리 포기하고 힌트를 보고 풀었습니다ㅠㅠ

     다른 것보다도 결국 DP에서는 아이디어가 중요한 것 같은데, 이전에 유사한 문제를 풀어봤음에도 불구하고 제대로 떠올리지 못했었습니다. 우선 여기서 행렬곱의 횟수는 3개의 연속된 숫자를 곱한 값인데, 이를 DP로 아래와 같이 정의됩니다.


    D(i, j) : i부터 j번째까지의 행렬을 곱하는 데 필요한 최소의 횟수
    D(i, j) = D(i, k) + D(k+1, j) + (A[i] * A[k+1] * A[j])
    


     점화식으로 세워둔 것과 내용이 조금 달라서 헷갈리실 수도 있는데, 점화식에서의 k는 i와 j사이에 있는 임의의 숫자입니다. 그래서 실제로 구현을 할 때에는, i+k와 같이 구현해 두었을 뿐입니다. 조금 더 생각해봤다면 풀었을 수도 있었을텐데 조금 아쉽습니다.




    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.StringTokenizer;
    
    public class MatrixManipulation {
    
        public static int N = 0;
        public static int matrixs[] = null;
        public static int cache[][] = null;
    
        public static void main (String[] args) throws Exception {
    
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            N = Integer.parseInt(br.readLine());
    
            matrixs = new int[N + 2];
            cache = new int[N+1][N+1];
            StringTokenizer st = new StringTokenizer(br.readLine());
            for (int i = 1; i < N+2 ; i++){
                matrixs[i] = Integer.parseInt(st.nextToken());
            }
    
            int result = dp(1, N);
            System.out.println(result);
        }
    
        // i번째부터 j번째까지 행렬의 곱연산 최소 수를 리턴
        public static int dp (int i, int j) {
    
            if (i == j-1) {
                return matrixs[i] * matrixs[i+1] * matrixs[i+2];
            } else {
                if (i >= j){
                    return 0;
                }
                if(cache[i][j] != 0) {
                    return cache[i][j];
                }
            }
    
            int ret = Integer.MAX_VALUE;
            for (int k = 0 ; k < j-i ; k++) {
                ret = Math.min(ret, dp(i, i+k) + dp(i+k+1, j) + (matrixs[i] * matrixs[i+k+1] * matrixs[j+1]));
            }
    
            return cache[i][j] = ret;
        }
    }
    


    댓글

Designed by Tistory.