[BOJ] Q11049 행렬 곱셈 순서

Question

Language: Python

Difficulty: Gold 3

A1=5X3 A2=3X2 A3=2X6 으로 이루어진 행렬이 있다고 했을때,

A1,A2,A3 행렬에 대해서 행렬 곱 연산을 구하는 과정은 ((A1,A2),A3) ==> 5X3X2 + 5X2X6 = 90 (A1,(A2,A3)) ==> 3X2X6 + 5X3X6 = 126 와 같이 총 2가지 경우가 존재한다. 아래의 경우로 행렬 연산을 수행했을 때, 최소 곱 연산으로 구할 수 있다.

A1,A2,A3,A4가 있을 때는 어떻게 될까? (A1),(A2,A3,A4) = A1-A1의 행렬곱(0) + A2-A4 행렬곱+ A1 row * A1[col] * A4[col] (A1,A2),(A3,A4) = A1-A2의 행렬곱 + A3-A4 행렬곱+ A1 row * A2[col] * A4[col] (A1,A2,A3),(A4) = A1-A3의 행렬곱 + A4-A4 행렬곱(0)+ A1 row * A3[col] * A4[col]

을 비교해서 최소 횟수를 구해야한다.

이처럼 행렬 연산 순서에 따라 행렬 곱의 연산 회수는 달라지기 때문에 비교를 해야된다.

A1A2A3…An이 있을 때, 해당 행렬 곱의 최소 연산 아래와 같이 구할 수 있다.

A1An=min((A1Ak) + (Ak+1An) for 1<=i<=n)와 같은 점화식을 통해 각각의 최저 연산 횟수를 구할 수 있다.

이것을 이차원 배열로 생각해보면 쉽다

위의 예제를 예시로 들어보자

  A1 A2 A3
A1 0 A1A2
A2 0 A2A3
A3 0

맨 마지막에 들어가는 칸은 A1A3 으로 (A1A2)A3 , A1(A2A3) 을 비교를 통해서 구한다. 행/열 차이가 1인 행렬들 부터 비교해가면서 A1An=min((A1Ak) + (Ak+1An) 해당 연산 결과들을 비교한다.

Solution

from math import inf
def solution():
    dp=[[0] * (num+1) for _ in range(num+1)]
    for diagonal in range(1,num):
        for i in range(0,num-diagonal):
            j=i+diagonal
            if diagonal==1:
                dp[i][j]=matrices[i][0]*matrices[i][1]*matrices[j][1]
                continue   
            dp[i][j]=inf
            for k in range(i,j):
                dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+matrices[i][0]*matrices[k][1]*matrices[j][1])
    print(dp[0][num-1])  
if __name__ == "__main__":
    num=int(input())
    matrices=[list(map(int,input().split())) for _ in range(num)]
    solution()

댓글남기기