행렬 체인 곱셈 최적화 여야합니다. 이것은 다음에 수행 할 곱셈의

이 과제는 여러 행렬의 곱에 대해 가장 효율적인 곱셈 순서 를 계산 하는 것입니다.

행렬의 크기는 한 줄의 표준 입력에 지정됩니다. 총 곱셈 비용을 최소화하기 위해 곱셈을 수행하는 순서를 나타내는 정수 목록을 표준 출력으로 인쇄해야합니다.

예 1

입력

5x6 6x12 12x100 100x7

산출

3 2 1

입력 행은 공백으로 구분 된 행렬 크기 목록이며, 각 행은 행 수, 그 뒤에 x, 열 수입니다. 예를 들어, 곱하기위한 4 개의 행렬이 있으므로 (총 3 개의 곱셈) 행렬 곱셈은 연관되어 있으므로 순서에 관계없이 수행 할 수 있습니다.

결과는 총 비용을 최소화하기 위해 곱셈을 수행하는 순서 여야합니다. 이것은 다음에 수행 할 곱셈의 인덱스를 나타내는 공백으로 구분 된 정수 목록이어야합니다. N 행렬의 경우이 목록에는 1에서 N-1까지의 숫자가 포함되어야합니다. 예를 들어 1의 출력 3 2 112x100 * 100x7곱셈을 먼저 수행 한 다음 6x12 * 12x7곱셈 (두 번째 행렬에 이전 단계의 결과를 5x6 * 6x7곱한 값)을 곱한 다음 최종 곱셈을 수행해야 함을 의미합니다 .

행렬 곱셈은 항상 호환 가능합니다. 즉, 행렬의 열 수는 후속 행렬의 행 수와 일치합니다. 두 행렬 승산 비용 가정 AxB * BxC이다 A*B*C.

코드는 최대 100 개의 행렬, 각 차원의 최대 999 개의 목록을 처리해야하며 적절한 시간에 처리해야합니다.

예 2

입력

5x10 10x5 5x15 15x5

산출

1 3 2

또는

3 1 2

예 3

입력

22x11 11x78 78x123 123x666 666x35 35x97 97x111 111x20 20x50

산출

2 3 4 5 6 7 8 1

참고 : 검증을 위해 세 가지 예의 총 총 비용은 9114, 750 및 1466344입니다.

최단 코드 승리!



답변

루비 176 개 172 205 문자

합리적인 시간에 큰 입력을 위해 실행되는 다른 버전 (여러 문자가 더 길다)이 있습니다.

q=(gets.split<<$_[/\d+$/]).map &:to_i
r=Hash.new{|h,i|h[i]=Hash.new{|h,j|h[j]=1e12;h[j]=i==j ?[0,[]]:(i...j).map{|k|a,c=r[i][k];b,d=r[k+1][j];[a+b+q[i-1]*q[k]*q[j],c+d+[k]]}.min}}
$><<r[1][q.size-1][1]*' '

첫 번째 버전 : Ruby에서 직접 재귀 구현. 완전한 검색을 수행하므로 큰 입력에서 느려질 수 있습니다.

k=->m{m[2]?(1..m.size-2).map{|l|s=k[m[0,l]+m[l+1..-1]];[m[l-1]*m[l]*m[l+1]+s[0],[l]+s[1].map{|u|u<l ?u:u+1}]}.min: [0,[]]}
$><<k[(gets.split<<$_[/\d+$/]).map &:to_i][1]*' '