动态规划(三)--矩阵链乘法

问题描述:

给定n个矩阵的链<A1,A2,...,An>,矩阵Ai的规模为Pi-1XPi。求完全括号方案使得计算乘积所需的标量乘法次数最少。

为了计算上式,我们可以先用括号明确计算次序,然后利用标准矩阵相乘方法进行计算。例如矩阵链<A1,A2,A3,A4,A5>,由于矩阵乘法满足结合律,所以可以有((A1A2)(A3A4)A5)或(A1(A2(A3A4))A5)等计算次序。而对于相容的矩阵A,B,若A矩阵为p*q,B矩阵为q*r,那么乘积C是p*r的矩阵,而计算时间是标量乘法的次数决定的即p*q*r。假设有三个矩阵的规模为10*100,100*5,5*50,如果按照((A1A2)A3)的顺序计算则需要7500次标量乘法,若按(A1(A2A3))次序计算,需要75000次乘法,时间相差了十倍。。要明确的是我们的目标是确定代价最低的计算顺序,并不是真正进行矩阵相乘。

令P(n)表示可供选择的括号化方案的数量,则p(n)=1(n=1);

     p(n)=∑p(k)p(n-k) (n>=2);

对应第一篇的原理,

Step1:我们要寻找最优子结构,对应Ai~Aj(i<j),为了对Ai...Aj进行括号化,需要在某个Ak和Ak+1之间将矩阵链分开,然后在计算乘积得到结果Aij,即原问题可以分解成为两个互不相干的子问题并分别进行独立求解

Step2:一个递归的求解方案

显然最低代价m[i,j]=0(i=j)   ;   m[i,j]=min{m[i,k]+m[k+1,j]}+Pi-1PkPj(i<j)

step3:计算最优代价

采用子底向上的方法,用一个一维数组p[n+1]来表示矩阵链,用一个二维数组m[i][j]来保存代价,用另一个辅助二维数组s[i][j]记录最优值对应的分割点k,我们就可以用s来构造最优解了

pseudoCode

MATRIX-CHAIN-ORDER(p)

n = p.length -1

  let m and s be new tables

for i = 1  to n

m[i][i] = 0

for l = 2 to n

for i =1 to n-l+1

j=i+l-1

m[i,j] = max

for k = i to j-1

q=m[i,k]+m[k+1,j]}+Pi-1PkPj

 ifq<m[i,j]

m[i,j] = q

s[i,j] = k

return m and s


java代码

import java.util.Arrays;


/**
 * @author Bangwen Chen
 *
 * 2013-8-22
 */
public class Matrix_chain_order {
	public static void main(String [] args){
		int[]p = {30,35,15,5,10,20,25};
		chain_order(p);
	}
	static void chain_order(int []p){
		final double MAX=1E10f;
		int n = p.length-1;
		 double [][]m = new double[n+1][n+1];
		double [][]s = new double [n+1][n+1];
		for(int i=1;i<n+1;i++){
			m[i][i]=0;
		}
		for(int l=2;l<n+1;l++){
			for(int i=1;i<n-l+2;i++){
				int j=i+l-1;
				m[i][j]=MAX;
				for(int k=i;k<j-1+1;k++){
					double q = (double)m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
					System.out.println("q" + q);
					if(q<m[i][j]){
						m[i][j] = q;
						s[i][j] = k;
					}
				}
			}
		}
		display(m);
		System.out.println("-------------------");
		display(s);
	}
	static void display(double [][] array){
		int n = array[0].length;
		for(int i=1;i<n;i++){
			for(int j=1;j<n;j++){
				System.out.print(array[i][j]+" ");
			}
			System.out.print("\n");
		}
	}
}

step 4 构造最优解,Matrix-chain-order求出了最少的标量乘法,但它并未指出如何进行这种最优代价的矩阵链乘法计算,s中保存了最优解,利用递归给出。

pseudocode

PRINT-OPTIMAL-PARENS(s,i,j)

if i == j

print Ai;

else

print "("

PRINT-OPTIMAL-PARENS(s,i,s[i,j])

PRINT-OPTIMAL-PARENS(s,s[i,j+1,j)

print")"

Java代码

import java.util.Arrays;


/**
 * @author Bangwen Chen
 *
 * 2013-8-22
 */
public class Matrix_chain_order_display {
	public static void main(String [] args){
		int[]p = {30,35,15,5,10,20,25};
		int [] array = {5,10,3,12,5,50,6};
		chain_order(array,1,6);
	}
	static void chain_order(int []p,int start,int end){
		final double MAX=1E10f;
		int n = p.length-1;
		 double [][]m = new double[n+1][n+1];
		double [][]s = new double [n+1][n+1];
		for(int i=1;i<n+1;i++){
			m[i][i]=0;
		}
		for(int l=2;l<n+1;l++){
			for(int i=1;i<n-l+2;i++){
				int j=i+l-1;
				m[i][j]=MAX;
				for(int k=i;k<j-1+1;k++){
					double q = (double)m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
					System.out.println("q" + q);
					if(q<m[i][j]){
						m[i][j] = q;
						s[i][j] = k;
					}
				}
			}
		}
		display(m);
		System.out.println("-------------------");
		display(s);
		String A[]=new String [n+1];
		for(int z=1;z<n+1;z++){
			A[z] = "A".concat(String.valueOf(z));
		}
		print_optimal_parens(s,start,end,A);
	}
	
	static void display(double [][] array){
		int n = array[0].length;
		for(int i=1;i<n;i++){
			for(int j=1;j<n;j++){
				System.out.print(array[i][j]+" ");
			}
			System.out.print("\n");
		}
	}
	static void print_optimal_parens(double[][] s,int i,int j,String A[]){
		
		if(i == j){
			System.out.print(A[i]);
		}else{
			System.out.print("(");
			int tmp = (int) s[i][j];
			print_optimal_parens(s,i,tmp,A);
			print_optimal_parens(s,tmp+1,j,A);
			System.out.print(")");
		}
	}
}

Sep 2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
动态规划矩阵链乘法问题是指给定一系列矩阵,求解它们相乘的最少乘法次数。根据引用\[2\]中的解释,我们可以使用一个二维数组m来表示矩阵相乘所要的最少乘法次数。其中,m\[i, j\]表示从矩阵i到矩阵j相乘所要的最少乘法次数。 根据引用\[3\]中的思路,当只有一个矩阵时,乘法次数为0;当有两个矩阵时,乘法次数矩阵行列直接相乘的结果。对于个及以上的矩阵,我们可以通过动态规划的方式来求解最少乘法次数。 具体的动态规划算法如下: 1. 初始化二维数组m的对角线元素为0,表示只有一个矩阵时的乘法次数为0。 2. 从长d=2开始,逐步增加长,计算m\[i, j\]的值。对于每个长d,遍历所有可能的分割点k,计算m\[i, j\]的值。具体计算方式为:m\[i, j\] = min{m\[i, k\] + m\[k+1, j\] + a\[i\]*a\[k\]*a\[j+1\]},其中a\[i\]表示第i个矩阵的行数,a\[j+1\]表示第j+1个矩阵的列数。 3. 最终,m\[1, n\]即为所求的最少乘法次数,其中n为矩阵的长度。 通过以上算法,我们可以得到矩阵相乘的最少乘法次数。这个问题的动态规划解法可以有效地减少重复计算,提高计算效率。 #### 引用[.reference_title] - *1* *2* *3* [动态规划——矩阵相乘](https://blog.csdn.net/Wu_L7/article/details/124327310)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值