日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

动态规划之矩阵连乘讲解

發布時間:2025/3/16 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态规划之矩阵连乘讲解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

注:當時在學矩陣連乘的時候,在網上發現這篇文章總結的不錯,便摘抄了下來,今天與大家共享。同時望原創不要見怪!

動態規劃之矩陣連乘

給定n個矩陣{A1,A2,,An},其中AiAi+1是可乘的,i=1,2,,n-1??疾爝@n個矩陣的連乘積A1A2An。由于矩陣乘法滿足結合律,故計算矩陣的連乘積可以有許多不同的計算次序,這種計算次序可以用加括號的方式來確定。若一個矩陣連乘積的計算次序完全確定,則可以依此次序反復調用2個矩陣相乘的標準算法(有改進的方法,這里不考慮)計算出矩陣連乘積。若A是一個p×q矩陣,B是一個q×r矩陣,則計算其乘積C=AB的標準算法中,需要進行pqr次數乘。

矩陣連乘積的計算次序不同,計算量也不同,舉例如下:

先考察3個矩陣{A1,A2,A3}連乘,設這三個矩陣的維數分別為10×100100×55×50。若按((A1A2A3)方式需要的數乘次數為10×100×510×5×507500,若按(A1A2A3))方式需要的數乘次數為100×5×5010×100×5075000。

下面使用動態規劃法找出矩陣連乘積的最優計算次序。

1??設矩陣連乘積AiAi+1Aj簡記為A[i:j],設最優計算次序在AkAk+1之間斷開,則加括號方式為:

((AiAi+1Ak)(Ak+1Aj))

則依照這個次序,先計算A[i:k]A[K+1:j]然后再將計算結果相乘,計算量是:

A[i:k]的計算量加上A[K+1:j]的計算量再加上它們相乘的計算量。

問題的一個關鍵是:計算A[i:j]的最優次序所包含的兩個子過程(計算A[i:k]A[K+1:j])也是最優次序。

2??設計算A[i:j]所需的最少數乘次數為m[i][j]

i=j時為單一矩陣,則m[i][i]=0

i<j時,設最優計算次序在AkAk+1之間斷開,則m[i][j]=m[i][k]+m[k+1][j]+pipk+1pj+1,其中p表示數組的維數,例如A0A56個數組(為了C語言的描述方便,下標從0開始),他們表示如下:

//p[0]:第一個矩陣的行數

????//p[1]:第一個矩陣的列數,第二個矩陣的行數

????//p[2]:第二個矩陣的列數,第三個矩陣的行數

k此時并未確定,需要從ij-1遍歷以尋找一個最小的m[i][j]。我們把這個最小的k放在s[i][j]。

?

以下是完整實現代碼,以一個具體的例子實現,稍加修改即可通用。

#include?<iostream>

using?namespace?std;

//

//MatrixChain計算m[i][j]所需的最少數乘次數

//并記錄斷開位置s[i][j]

//

void?MatrixChain(int?*p,int?n,int?**m,int?**s)

{

?????for(int?i=0;i<n;i++)

?????????m[i][i]=0;//單個矩陣相乘,所需數乘次數為0

?

?????//以下兩個循環是關鍵之一,以6個矩陣為例(為描述方便,m[i][j]用ij代替)

?????//需按照如下次序計算

?????//01?12?23?34?45

?????//02?13?24?35

?????//03?14?25

?????//04?15

?????//05

?????//下面行的計算結果將會直接用到上面的結果。例如要計算14,就會用到12,24;或者13,34等等

?????for(int?r=1;r<n;r++)

?????{

?????????for(int?i=0;i<n-r;i++)

?????????{

??????????????int?j=i+r;

??????????????//首先在i斷開,即(Ai*(Ai+1...Aj))

??????????????m[i][j]=m[i][i]+m[i+1][j]+p[i]*p[i+1]*p[j+1];

??????????????s[i][j]=i;

??????????????for(int?k=i+1;k<j;k++)

??????????????{

???????????????????//然后在k(從i+1開始遍歷到j-1)斷開,即((Ai...Ak)*(Ak+1...Aj))

???????????????????int?t=m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1];

???????????????????if(t<m[i][j])//找到更好的斷開方法

???????????????????{

???????????????????????m[i][j]=t;//記錄最少數乘次數

???????????????????????s[i][j]=k;//記錄斷開位置

???????????????????}

??????????????}

?????????}

?????}

?????//如果使用下面注釋的循環,則是按照如下次序計算

?????//01?02?03?04?05

?????//12?13?14?15

?????//23?24?25

?????//34?35

?????//45

?????//當要計算時14,會用到12,24,而此時24并沒有被計算出來。

/*

?????for(int?i=0;i<n;i++)

?????{

?????????for(?int?j=i+1;j<n;j++)

?????????{

??????????????m[i][j]=m[i][i]+m[i+1][j]+p[i]*p[i+1]*p[j+1];

??????????????s[i][j]=i;

??????????????for(int?k=i+1;k<j;k++)

??????????????{

???????????????????int?t=m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1];

???????????????????if(t<m[i][j])

???????????????????{

???????????????????????m[i][j]=t;

???????????????????????s[i][j]=k;

???????????????????}

??????????????}

?????????}

?????}

?????*/

}

//

//Traceback打印A[i:j]的加括號方式

//

void?Traceback(int?i,int?j,int?**s)

{

?????//s[i][j]記錄了斷開的位置,即計算A[i:j]的加括號方式為:

?????//(A[i:s[i][j]])*(A[s[i][j]+1:j])

?????if(i==j)return;

?????Traceback(i,s[i][j],s);//遞歸打印A[i:s[i][j]]的加括號方式

?????Traceback(s[i][j]+1,j,s);//遞歸打印A[s[i][j]+1:j]的加括號方式

?

?????//能走到這里說明i等于s[i][j],s[i][j]+1等于j

?????//也就是說這里其實只剩下兩個矩陣,不必再分了

?????cout<<"A"<<i<<"和A"<<(s[i][j]+1)<<"相乘"<<endl;???

}

?

int?_tmain(int?argc,?_TCHAR*?argv[])

{

?????int?n=6;//矩陣的個數

?????int?*p=new?int[n+1];

?????//p[0]:第一個矩陣的行數

?????//p[1]:第一個矩陣的列數,第二個矩陣的行數

?????//p[2]:第二個矩陣的列數,第三個矩陣的行數

?????p[0]=30;

?????p[1]=35;

?????p[2]=15;

?????p[3]=5;

?????p[4]=10;

?????p[5]=20;

?????p[6]=25;

?

?????int?**m,**s;

?????m=new?int*[n];

?????for(?int?i=0;i<n;i++)

?????????m[i]=new?int[n];

?

?????s=new?int*[n];

?????for(int?i=0;i<n;i++)

?????????s[i]=new?int[n];??

?

?????MatrixChain(p,n,m,s);

?????Traceback(0,n-1,s);

for(int?i=0;i<n;i++)??

?????????{??

??????????????delete?[]m[i];

??????????????m[i]=NULL;

??????????????delete?[]s[i];

??????????????s[i]=NULL;

?????????}??

?????????delete?[]m;??

?????????m=NULL;?

?????????delete?[]s;??

?????????s?=?NULL;

?????????delete?[]p;??

?????????p?=?NULL;?

?????return?0;

}

打印結果是:

A1A2相乘

A0A1相乘

A3A4相乘

A3A5相乘

A0A3相乘

實際上要表達的是如下加括號方式:

((A0A1A2))((A3A4A5))

加了括號之后用第一個來代替,例如(A1A2)可看作A1,這個結果的數乘次數是15125。

?

具體實例見:

NYOJ 460 項鏈

NYOJ 536 開心的mdd



總結

以上是生活随笔為你收集整理的动态规划之矩阵连乘讲解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。