동적 계획 매트릭스 체인 곱셈


 
Description
n 개의 행렬 (A1, A2,..., An 곶 을 지정 합 니 다. 그 중에서 Ai 와 Ai + 1 은 탈 수 있 습 니 다. i = 1, 2,..., n - 1.어떻게 행렬 의 곱 하기 계산 순 서 를 확정 하여 이 순서에 따라 행렬 의 곱 하기 에 필요 한 곱 하기 횟수 를 가장 적 게 계산 합 니까? 
Input
N 개의 행렬 연결 이 있 습 니 다. 한 줄 에 n + 1 개의 배열 로 n 개의 행렬 의 줄 과 n 번 째 행렬 의 열 을 표시 합 니 다. 그들 사 이 는 빈 칸 으로 구분 합 니 다. 
Output
출력 은 C 줄 이 있어 야 합 니 다. 즉, 각 테스트 데이터 의 출력 이 한 줄 을 차지 해 야 합 니 다. 행렬 의 최소 곱 하기 횟수 를 계산 하고 출력 이 가장 좋 은 괄호 구조 입 니 다.
Sample Input
10 100 5 50

 
 
Sample Output
 
7500
((A1A2)A3)

 
 
분석:
 
행렬 체인 곱셈 문제 설명:
 n 개의 행렬 로 구 성 된 서열 [A1, A2,..., An] 을 정 하고 곱셈 A1A 2... An 에 대해 곱셈 횟수 를 최소 화 하 는 괄호 방법 을 찾 습 니 다.
 1) 최 우선 서브 구조 찾기
이 문제 의 가장 어 려 운 점 은 가장 좋 은 서브 구 조 를 찾 는 것 이다.곱 하기 A1A 2... An 의 임 의 괄호 넣 기 방법 은 모두 서열 을 어 딘 가 에 두 부분 으로 나 누 는데 그것 이 바로 마지막 곱셈 으로 계산 하 는 곳 이다. 우 리 는 이 위 치 를 k 로 기록한다. 즉, A1... Ak 와 Ak + 1... An 을 먼저 계산 한 다음 에 이 두 부분의 결 과 를 곱 하 는 것 이다.
가장 좋 은 서브 구 조 는 다음 과 같다. 만약 에 A1A 2. An 의 가장 좋 은 괄호 가 Ak 와 Ak + 1 사이 에 곱 하면 접두사 체인 A1... Ak 의 괄호 방식 은 반드시 A1... Ak 의 가장 좋 은 괄호 이 고 접두사 체인 은 똑같다.
처음에는 k 의 정확 한 위 치 를 몰 랐 고 적당 한 k 를 찾 아 곱 하기 위해 모든 위 치 를 옮 겨 다 녀 야 했다.
 
2) 구조 재 귀 해
m [i, j] 를 매트릭스 체인 Ai... Aj 의 가장 좋 은 대가 로 설정 하면
          ┌ 0    하면, 만약, 만약...
m[i,j] = │
          └ min(i≤k<j) {m[i,k] + m[k+1,j] + Ai.row*Ak.col*Aj.col}  하면, 만약, 만약...
 
 3) 보조 표 구축, 중첩 자 문제 해결
두 번 째 단계 의 재 귀 식 을 통 해 알 수 있 듯 이 해 를 하 는 과정 에서 중첩 서브 문제 가 많 을 것 이다. nX n 차원 의 보조 표 t [n] [n] 으로 서브 문제 의 해 를 저장 할 수 있다. 표 에 있 는 모든 요 소 는 2 개의 정 보 를 포함 하고 각각 최 적 곱 하기 대가 와 분할 위치 k 이다. 。
보조 표 t [n] [n] 은 2 가지 방법 으로 구 조 될 수 있다. 하 나 는 아래 에서 위로 표를 작성 하여 구축 하 는 것 이다. 이 방법 은 증가 하 는 방식 에 따라 서브 문제 의 해 를 점차적으로 작성 해 야 한다. 즉, 길이 가 2 인 모든 행렬 체인 의 해 를 계산 한 다음 에 길이 3 의 행렬 체인 을 계산 하여 길이 n 까지 계산 해 야 한다.다른 하 나 는 위 에서 아래로 표를 작성 하 는 비망록 법 이다. 이 방법 은 표 의 모든 요 소 를 특정한 특수 값 으로 초기 화 하 는 것 이다.
비망록 법 은 아래 에서 위로 올 라 가 는 것 보다 상수 인자 가 느 릴 것 이다. 전 자 는 재 귀적 호출 의 대가 가 있 기 때문에 표를 지 키 는 비용 도 약간 크다.
 
 
 
#include #include #include #define N 6 void Print_OPTIMAL_(int s [N + 1] [N + 1] [N + 1], int i, int j) / / 정의 함수 가 가장 좋 은 괄호 를 출력 한 결과 {if (i = = j) printf ("A% d", i); else {printf ("("); print OPTIMAL PARENS (s, i, s [i]] [j]); / / / 분 열 된 부분 에서 재 귀적 으로 print OPTIMAL PAREN PARENS (s, s [[] [j] + 1, j); printf (")");} int main main main (main (mat) {int int int int int int (int) {int int int int int int (int) {int int int int int int int int (int) {int int int int int. int (int) {rix [N + 1]; / / matrix 에 기 록 된 행렬 의 비트 int i, j, k, q; int m [N + 1] [N + 1]; / / m 에서 행렬 의 연 승 횟수 를 기록 한 int s [N + 1] [N + 1]; / / [i] [j] [j] 에 서 는 Ai... Aj 를 분열 시 키 는 가장 좋 은 k 값 for (i = 0; i < = N; i + + +) scanf ("% d", & matrix [i]; memset (m, 0, (N + 1) * (N + 1) * size of (int)); for (j = 1; j < < < = N; j < = j + + + +) for (i = j; i = j; i > = i > = 1; i - - -) / i = j = j 일 때, m [i]] [j = 0]] [j = 0, {{0, {0, {0, {0, {0, {/ / i < j 시, m [i] [j] = min {m [i] [k] + m [k + 1] [j] + p (i - 1) p (k) p (j)} i = < k < j if (j = i) m [i] [j] = 0; else{ m[i][j]=600000; for (k=i;k또 다른 최 적 화 된 매트릭스 체인 방식 함수:
이 함 수 는 아래 에서 위로 계산 하 는 방법 을 채택 한다.
 
void Matrix Chain () {int i, j, k, t;i 개의 행렬 에서 시작 되 는 연속 r 개의 행렬 을 곱 하 는 최소 횟수 를 계산 하 는 j = i + r - 1; / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / for (k = i + 1; k < j; k + +){ t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j]; if( t < m[i][j]) m[i][j] = t; } } } } 
 

좋은 웹페이지 즐겨찾기