矩阵连乘(区间DP)

2023-08-24   


题意:

计算A0A1A2....AnA_0A_1A2....A_n矩阵连乘需要的最少计算量。
ApqA_{p*q}BqrB_{q*r}相乘计算量为pqrp*q*r

分析:

状态表示——集合F[i][j]F[i][j] 矩阵Ai....AjA_i....A_j的连乘数。
状态表示——属性F[i][j]F[i][j] 矩阵Ai....AjA_i....A_j的连乘乘积数最小值

i=ji=j时,F[i][j]F[i][j]相当于一个矩阵AiA_i,故此时F[i][j]=0F[i][j]=0

i<ji<j时,假设F[i][j]F[i][j]的最优次序在AkA_kAk+1A_{k+1}断开,故有F[i][j]=f[i][k]+f[k+1][j]+Pi1PkPjF[i][j]=f[i][k]+f[k+1][j]+P_{i-1}P_kP_j
其中PP数组为矩阵AijA_{ij}的维数。

最后的答案即F[1][n]F[1][n]

时间复杂度: O(n3)O(n^3)

矩阵连乘

代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;

const int N = 105;

int n;
int p[105];
int f[105][105];

void dp() {
	for(int i = 1; i <= n; i ++)	f[i][i] = 0;
	for (int len = 2; len <= n; len ++) { //枚举长度 
		for (int i = 1; i <= n - len + 1; i ++) { // 起点 
			int j = i + len - 1;
			f[i][j] = f[i][i] + f[i + 1][j] + p[i - 1] * p[i] * p[j];
			for (int k = i + 1; k < j; k ++) { // 枚举分界点 
				f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + p[i - 1] * p[k] * p[j]);
			}
		}
	}
}

int main() {

	scanf("%d", &n);
	for (int i = 0; i <= n; i ++) {
		scanf("%d", &p[i]);
	}
	dp();
	printf("%d\n", f[1][n]); 
	return 0;
} 

题目链接:矩阵连乘

Q.E.D.