動態規劃 矩陣鏈乘問題分析

2021-07-11 16:07:09 字數 3398 閱讀 7009

一.問題簡述

給定n個矩陣,其中a i 和a i+1 是可乘的,這n個矩陣的連乘積a 1 a 2 …a n 。由於矩陣的乘法滿足結合律,故計算矩陣的連乘積有許多不同的計算次序,而不同的計算次序,所需要計算的連乘次數也是不同的,求解連乘次數最少的矩陣連乘最優次序。

輸入乙個序列p=,矩陣a的維數為pi-1*pi。

假設有三個矩陣a1、a2、a3,三個矩陣的維數分別為10*100,100*5,5*50,則p=

二.演算法分析

按照動態規劃法處理問題的步驟:

(1)最優加括號的全部結構

動態規劃方法的第一步是尋找最優子結構,然後,利用這一子結構,就可以根據子問題的最優解構造出乙個原始問題的最優解。用記號ai..j表示對乘積aiai+1…aj求值的結果;對ai…aj任何加括號的形式都將在ak,與ak+1之間分開。也就是說,對於某個k值,先計算ai..k和ak+1..j然後再把他們相乘,這樣就得到最終乘積ai…j。

(2)乙個遞迴解

對於矩陣鏈乘問題,子問題就是確定aiai+1…aj的加全部括號的最小代價問題,1<=i<=j<=n,m[i,j]為計算矩陣ai..j所需的標量乘法運算的最小值;對於整個問題,計算a1…n的最小代價就是m[1,n]。

(1)矩陣鏈只包含乙個矩陣,即i=j時,m[i,i] = 0;

(2)i < j時,m[i,j]=m[i,k]+m[k+1,j]+pi-1*pk*pj

所以,最優值可以遞迴的定義為:

(3)計算最優代價

使用自底向上的**法來求解最優代價,輸入的是乙個序列p=,表示有n個矩陣相乘a1的維數為p0*p1,a2的維數為p1*p2……以此類推,直到an…,m[1…n,1..n]來儲存m[i,j]的代價,表s[1..n,1..n]來記錄m[i,j]時取得最優代價k的值,即插入括號的位置。

**實現:

#include 

#include

#include

#define max 100

/*動態規劃矩陣鏈乘*/

typedef struct

res;

void initp(int* p,int length)

}res matrix_chain_order(int* p,int length)}}

}return

count;

}

我們現在舉例分析假設輸入的序列p=,表示6個矩陣:

矩陣維數

a130*35

a235*15

a315*5

a45*10

a510*20

a620*25

n = length -1;即n=6,為矩陣的個數,中間程式是三層for迴圈巢狀,現在,我們分析程式執行的過程。(l為子問題的規模)

1.◆l=2;l<=n=6;l++(l為子問題的規模),一重for迴圈

●i=1;i<=n-l+1=5;(i為子問題前端點的範圍),二重for迴圈

j=2=i+l-1;(j為子問題後端點的範圍)

m[1,2]=m[i,j]=∞

★     k=i=1;k<=j-1=1;三重for迴圈

q=m[1,1]+m[2,2]+p0*p1*p2=0+0+15750=15750

if (q < count.m[i][j])即15750

m[1,2]=15750;

s[1,2]=k=1;

返回到★處執行k=2時,不滿足for迴圈,返回上一層for迴圈●處,執行i=2,j=3;因此,我們觀察,當子問題規模為l=2時,有以下幾種情況:

子問題規模為2,l=2

m[1,2]=m[1,1]+m[2,2]+p0*p1*p2=0+0+15750=15750  s[1,2]=1

m[2,3]=m[2,2]+m[3,3]=p1*p2*p3=2625  s[2,3]=2

m[3,4]=m[3,3]+m[4,4]=p2*p3*p4=750 s[3,4]=3

m[4,5]=m[4,4]+m[5,5]=p3*p4*p5=1000 s[4,5]=4

m[5,6]=m[5,5]+m[6,6]=p4*p5*p6=5000 s[5,6]=5

2.l=3時,

子問題規模為3,l=3

m[1,3]=min(m[1,1]+m[2,3]+p[0]*p[1]*p[3],m[1,2]+m[3,3]+p[0]*p[2]*p[3]);

m[2,4]=min(m[2,2]+m[3,4]+p[1]*p[2]*p[4],m[2,3]+m[4,4]+p[1]*p[3]*p[4]);

m[3,5]=min(m[3,3]+m[4,5]+p[2]*p[3]*p[5],m[3,4]+m[5,5]+p[2]*p[4]*p[5])

m[4,6]=min(m[4,4]+m[5,6]+p[3]*p[4]*p[6],m[4,5]+m[6,6]+p[3]*p[5]*p[6])

迭代執行該過程,直到l=6為止;

計算過程:

(4)構造最優解

即根據s[1…n,1…n]記錄的資料列印出最優加括號的位置k

void print_optimal_parens(int (*s)[max],int i,int j)

else

}

main函式呼叫的格式:

printf("請輸入下標i,j的值,即輸出最優加全部括號的形式(i,j取值在1~%d之間)\n",length-1);

printf("i=");scanf("%d",&i);

printf("j=");scanf("%d",&j);

printf("%d,a%d,...a%d>最優加全部括號的形式\n",i,i+1,j);

print_optimal_parens(count.s,i,j);

三.總結執行結果:

matrix_chain_order三層巢狀,執行時間為o(n*n*n)

reference:

(1)《演算法導論》15.2矩陣鏈乘法

(2)(3)

矩陣鏈乘 動態規劃

普通矩陣相乘 define row a 2 define col a 2 define col b 3 void matrix mul int mata row a col a int matb 2 col b int c row a col b 兩個相容矩陣相乘,相容是指矩陣a的行必須等於矩陣b的...

動態規劃經典問題 矩陣鏈乘

問題描述 給定n個矩陣,其中ai與ai 1是可乘的,i 1,2,3.n 1.考慮這n個矩陣的乘積。由於矩陣乘法滿足結合律,故計算矩陣的連乘積可以有許多不同的計算機次序。這種計算次序可以用加括號的方式確定。若乙個矩陣鏈乘的計算次序完全確定,這時就說該鏈乘已完全加括號。完全加括號的矩陣鏈乘可遞迴的定義如...

C 動態規劃 矩陣鏈乘

c 動態規劃 矩陣鏈乘 1 問題描述 給定n個矩陣構成的乙個鏈給定 a1,a2,an 其中i 1,2,n.矩陣ai的維數為pi 1 pi,如何確定計算矩陣連乘積的計算次序,使得依此次序計算矩陣連乘積需要的數乘次數最少。2 最優子結構 對乘積a1a2.an的任意加括號方法都會將序列在某個地方分成兩部分...