算法設計與分析----矩陣連乘

給定n個矩陣{A1,A2,…,An},其中Ai與Ai+1是可乘的,i=1,2…,n-1。如何確定計算矩陣連乘積的計算次序,使得依此次序計算矩陣連乘積需要的數乘次數最少。例如,給定三個連乘矩陣{A1,A2,A3}的維數分別是10 * 100,100 * 5和5 * 50,採用(A1A2)A3,乘法次數爲10 * 100 * 5 + 10 * 5 * 50=7500次,而採用A1(A2A3),乘法次數爲100550+1010050=75000次乘法,顯然,最好的次序是(A1A2)A3,乘法次數爲7500次。

矩陣連乘問題,需要用動態規劃來解決,爲每個矩陣編號:
在這裏插入圖片描述
輸入矩陣:
在這裏插入圖片描述
用p數組來表示矩陣,因爲前一個矩陣的列是後一個矩陣的行,所以對於n個矩陣來講只需輸入n+1個數。1號矩陣 = p[0] * p[1] , 2號矩陣 = p[1] * p[2],…
我們假設1號矩陣到3號矩陣已經乘完,那麼得到了一個10 * 25 的矩陣(10 * 50 50 * 20 20 * 25得到的最後矩陣爲10 * 25 ),假設4號矩陣到5號矩陣也已經乘完,得到了25 * 100 的矩陣,那如果這兩個矩陣相乘,需要多少次呢?矩陣的乘法是一行乘一列這樣乘的,所以需要10 * 25 * 100 = 25000次乘法運算。10是一號矩陣的行,25是3號矩陣的列,100是5號矩陣的列,我們將矩陣乘法的最少次數保存到m[][]二維數組中,那麼m[1][5]就表示1號矩陣乘到5號矩陣需要的次數,拿上面的例子來說,m[1][5]=m[1][3]+m[4][5]+p[0]*p[3]*p[5],意思是說 1號到5號矩陣乘法的次數=1號矩陣乘到3號矩陣的次數 + 4號矩陣乘到5號矩陣的次數 + 這兩個乘法的次數(1號矩陣行 * 3號矩陣列 * 5號矩陣行 p[0]*p[3]*p[5]),而對於m[1][3]來說,也是類似於上面的求法,求出最小值。由此可以得出動態轉移方程:
當 i = j 時:
m[i][j] = 0
當 i < j 時:
m[i][j] = min{ m[i][k] + m[k+1][j] + pi-1 * pk * pj } , i<=k<j

#include<bits/stdc++.h>
using namespace std;
int p[100];
int m[50][50];
int s[50][50];
void print(int i,int j)
{
	if(i == j)
	{
		printf("A[%d]",i) ;
		return ;
	}	
	printf("(");
	print(i,s[i][j]);
	print(s[i][j]+1,j);
	printf(")");
}
int main()
{
	int n;
	scanf("%d",&n);
	for(int i = 0;i<=n;i++)
		scanf("%d",&p[i]);
	for(int step=2;step<=n;step++) //鏈長 
		for(int left=1;left<=n-step+1;left++)
		{
			int right = left+step-1;
			m[left][right] = m[left+1][right]+p[left-1]*p[left]*p[right];
			s[left][right] = left;
			for(int k=left+1;k<right;k++)
				if(m[left][k]+m[k+1][right]+p[left-1]*p[k]*p[right]<m[left][right])
					m[left][right] = m[left][k]+m[k+1][right]+p[left-1]*p[k]*p[right],s[left][right] = k;
		}
	printf("%d\n",m[1][n]);
	print(1,n);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章