动态规划之矩阵链乘法

矩阵链乘法

问题描述

给定一个 nn 个矩阵的序列(矩阵链) <A1,A2,…,AnA1,A2,…,An>,我们希望计算它们的乘积

 

A1A2…AnA1A2…An


为了计算表达式,我们可以先用括号明确计算次序,然后利用标准的矩阵相乘算法进行计算。由于矩阵乘法满足结合律,因此任何加括号的方法都会得到相同的计算结果。我们称有如下性质的矩阵乘积链为完全括号话:它是单一矩阵,或者是两个完全括号化的矩阵乘积链的积,且已外加括号。例如,如果矩阵链为<A1,A2,A3,A4A1,A2,A3,A4>,则共有 5 种完全括号化的矩阵乘积链:

(A1(A2(A3A4))),(A1(A2A3(A4))),((A1A2)(A3A4)),((A1A2A3)(A4)),(((A1A2)A3)A4)(A1(A2(A3A4))),(A1(A2A3(A4))),((A1A2)(A3A4)),((A1A2A3)(A4)),(((A1A2)A3)A4)


两个矩阵 AA 和 BB 只有相容,即AA的列数等于 BB 的行数时,才能相乘。如果 AA 是 p×qp×q 的矩阵,BB 是 q×rq×r 的矩阵那么乘积 CC 是 p×rp×r 的矩阵。计算 CC 的代价为 pqrpqr,我们使用标量乘法的次数来表示计算代价。
矩阵链乘法问题:给定 nn 个矩阵的链<A1,A2,…,AnA1,A2,…,An>,矩阵 AiAi 的规模为 pi−1×pi(1≤i≤n)pi−1×pi(1≤i≤n),求完全括号化方案,使得计算乘积 A1A2…AnA1A2…An所需的标量乘法次数最少。

动态规划求解

最优解结构

为了方便起见,我们用符号 Ai.j(i≤j)Ai.j(i≤j) 表示AiAi+1…AjAiAi+1…Aj 乘积的结果矩阵。
假设AiAi+1…AjAiAi+1…Aj 的最优括号化方案的分割点在 AkAk 和 Ak+1Ak+1 之间。那么,继续对”前缀”子链 AiAi+1…AkAiAi+1…Ak,”后缀” Ak+1Ak+2…AjAk+1Ak+2…Aj 进行括号化 (独立求解)。

递归定义

令 m[i,j]m[i,j] 表示计算矩阵 Ai.jAi.j 所需标量乘法次数的最小值,原问题的最优解—–计算A1..nA1..n 所需的最低代价就是 m[1,n]m[1,n]。
我们假设 AiAi+1…AjAiAi+1…Aj 的最优括号化方案的分割点在矩阵 AkAk 和 Ak+1Ak+1 之间,其中 i≤k<ji≤k<j。 那么,m[i,j]m[i,j] 就等于计算 Ai.kAi.k 和 Ak+1.jAk+1.j 的代价加上两者相乘的代价的最小值:

 

m[i,j]=m[i,k]+m[k+1,j]+pi−1pkpjm[i,j]=m[i,k]+m[k+1,j]+pi−1pkpj


因此递归求解公式为
if i==j

m[i,j]=0m[i,j]=0


else if i<j

m[i,j]=min{m[i,k]+m[k+1,j]+pi−1pkpj},i≤k<jm[i,j]=min{m[i,k]+m[k+1,j]+pi−1pkpj},i≤k<j

计算最优值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void getMatrixChanOrder(int[] p) {
	int n = p.length;
	long[][] dp = new long[n][n];
	int[][] s = new int[n][n];
	for (int i = 0; i < n; i++) {
		dp[i][i] = 0;
	}
	for (int l = 2; l < n; l++) {
		for (int i = 1; i <= n - l; i++) {
			int j = i + l - 1;
			dp[i][j] = Long.MAX_VALUE;
				for (int k = i; k < j; k++) {
				long temp = dp[i][j];
				dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k + 1][j] + p[i - 1] * p[k] * p[j]);
				if(temp!=dp[i][j]){
					s[i][j]=k;
				}
			}
		}
	}
	System.out.println(dp[1][n-1]+" "+s[1][n-1]);
}

假定矩阵 AiAi 的规模为 pi−1×pi,(i=1,2,…,n)pi−1×pi,(i=1,2,…,n),输入的序列 p=p=<p0,p1,…,pnp0,p1,…,pn>
比如:

矩阵A1A1A2A2A3A3A4A4A5A5A6A6
规模30×3530×3535×1535×1515×515×55×105×1010×2010×2020×2520×25

1
int[] p = { 30, 35, 15, 5, 10, 20, 25 };

 

构造最优解

1
2
3
4
5
6
7
8
9
10
public static void printOptimal(int[][] s,int i,int j){
	if(i==j){
		System.out.print("A"+i);
	}else{
		System.out.print("(");
		printOptimal(s,i,s[i][j]);
		printOptimal(s,s[i][j]+1,j);
		System.out.print(")");
	}
}

完整代码以及相应示例图见 https://github.com/lemon2013/algorithm/blob/master/MatrixChain.java

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值