1、矩阵连乘,tyvj 1198(最优矩阵连乘),关键是写出动态转移方程。用DP[i][j]表示矩阵Ai乘到Aj的最优解,P[]用来存储矩阵的行和列,M[i-1]表示矩阵i的行,M[i]表示矩阵i的列。
当i==j时,DP[i][i]=0;
当i<j时,可以假设他从k位置隔开。比方说从A3..A8。那么A1A2(A3A4A5A6A7A8)A9。我们知道若A矩阵为r1*c的矩阵,A2为c*r2的矩阵,得到的将是一个r1*r2的矩阵,且连乘次数为r1*c*r2。假设我从5位置隔开,就可以分为A1A2((A3A4A5)(A6A7A8))A9。那么这个时候的次数为:DP[3][5]+DP[6][8]+M[2]*M[5]*M[8](A3的行*A5的列*A8的列)。那么我只需要模举这其中的组合然后取最小值即可,这个时候的动态转移方程为:DP[i][j]=min(DP[i][k]+DP[k+1][j]+M[i-1]*M[k]*M[j])(i<=k<j)。
问题是:你要知道DP[i][k]和DP[k+1][j]的值,你才可以和DP[i][j]做比较,才能求出DP[i][j]的值。
思想是先求出相邻组的连乘次数,如一开始算相邻两个相乘,如图:
那么每两个相乘的结果我们可以得到。同理继续求三个相邻的结果。
计算的话比方说要求A1A2A3,可以化为(A1)(A2A3)=DP[1][1]+DP[2][3]+M[0]*M[1]*M[3],依次类推结果为:DP[i][j]=DP[i][i]+DP[i+1][j]+M[i-1]*M[i]*M[j]。
只有这样做后我才可以求任意组合的次数,求出三个一组的结果后,我就可以求任意的四个矩阵连乘的最小值。如:A4A5A6A7,随便怎么组合,通过上面是计算都可以求出相应的结果。
现在讨论下范围:用r保存要求的每每相邻的组数(2<=r<=n)(从2开始是这里前提条件是i<j),i的范围为:(1<=i<=n-r+1,稍作推理就知道,当r=3时,即三个三个一组时i<=9-3+1=7),j的值固定j=r+i-1,具体见代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAX=110;
#define min(a,b) (a)<(b)?(a):(b)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
int n,M[MAX],DP[MAX][MAX];
void Matrix()
{ for(int r=2;r<=n;r++)
for(int i=1;i<