MatrixMultiply(recursion、non-recursion)

输入:先输入矩阵连乘的个数n,然后依次手动输入(不能随机生成!)矩阵的维数pi(数字)。注意,6个矩阵,需输7个维数值。

输出:矩阵连乘的次序,如:((A1(A2A3))((A4A5A6))。

示例:输入:6  30  35  15  5  10  20  25,输出:((A1(A2A3))((A4A5)A6))


package FinalTest_3;

import java.util.Scanner;

/*矩阵可乘的条件是矩阵A的列数等于矩阵B的行数(A是一个p*q矩阵,B是一个q*r矩阵,乘积C=A*B是一个q*r矩阵,总共需要pqr次数乘)
 * 对于给定的矩阵,不同的加括号方式,矩阵连乘所需要的数乘次数也不同;
 * problem:对于给定的相继n个矩阵{A1,A2,...,An}(其中,矩阵Ai的维数为Pi-1*Pi,i=1,2,..,n),如何确定计算矩阵连乘积A1A2,...,An的计算次序(完全加括号方式),使得依此次序计算矩阵连乘积需要的数乘次数最少
 * 
 * 1.最优子结构:矩阵连乘积计算次序问题的最优解包含着其子问题的最优解(计算A[1,n]的最优次序所包含的计算矩阵子链A[1:k]和A[k+1:n]的次序也是最优的);
 * 2.递归方程:最优值min{m[i][j]=m[i][k]+m[k+1][j]+pi-1pkpj};计算A[i][j]的最优次序在Ak和Ak+1之间断开,i<=k<j ,k的位置有j-i个可能;k是这j-i个位置中使计算量达到最小的那个位置;
 *
 *
 *input:先输入矩阵连乘的个数n,然后依次手动输入(不能随机生成!)矩阵的维数pi(数字)。注意,6个矩阵,需输7个维数值。
 *output:矩阵连乘的次序,如:((A1(A2A3))((A4A5A6))。
 *示例:输入:6  30  35  15  5  10  20  25,输出:((A1(A2A3))((A4A5)A6))
 */

public class MatrixMultiply {
	
	static void Traceback(int i,int j,int arr2[][]){
		if(i==j) System.out.print("A" + i);
	/*	else if (i + 1 == j)
			System.out.print("(A" + i + "A" + j + ")");*/
		else {
			System.out.print("(");
			Traceback(i,arr2[i][j],arr2);
			Traceback(arr2[i][j]+1,j,arr2);
			System.out.print(")");
		}
	}
	
	
/*	static int matrixmultiply(int arr[][],int arr2[][],int p[],int n){		//自顶向下
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++) arr[i][j]=0;
		return LookupChain(arr,arr2,p,1,n);
	}
	
	private static int LookupChain(int arr[][],int arr2[][],int p[],int i,int j) {	//i是参加运算矩阵链起始位置,j是矩阵链终止位置
		if(arr[i][j]>0) return arr[i][j];		
		if(i==j) return 0;
		int u = LookupChain(arr,arr2,p,i,i)+LookupChain(arr,arr2,p,i+1,j)+p[i-1]*p[i]*p[j];		//取第一个断开位置时计算量
		arr2[i][j]=i;	//记录当前断开位置
			for (int k = i+1; k <j; k++) {
				int t = LookupChain(arr,arr2,p,i,k)+LookupChain(arr,arr2,p,k+1,j)+p[i-1]*p[k]*p[j]; //循环取k的可取断开位置
				if(t<u){u=t;arr2[i][j]=k;}	//发现更小的元素,记录
			}
			arr[i][j]=u;
			return u;
	}*/
	
	
	static void matrixmultiply(int arr[][],int arr2[][],int p[],int n){ 	//arr最优值,arr2最优值的断开点的索引,p计算次序,n矩阵的个数
		for (int i = 1; i <=n; i++) arr[i][i]=0;	//i=j,单一矩阵,无须计算
		for (int r = 2; r <=n; r++) {			//r为每次循环矩阵的层数(矩阵链长度),最大层为n
			for (int i = 1; i <=n-r+1; i++) {	//在第r层遍历(i,j),(1,2),(2,3),(3,4)..
				int j = i+r-1;		//j-i=r-1 ,第二层r=2,j-i=1;第三层r=3,j-i=2;...
				arr[i][j]=arr[i+1][j]+p[i-1]*p[i]*p[j];		//先计算A[i+1][j],
				arr2[i][j]=i;			//记录断开点的位置为arr的i坐标,arr2[1][2]=1;arr2[2][3]=2;..遍历顺序和arr数组一致
				for (int k = i+1; k <j; k++) {		//循环求出(Ai~Aj)中的最小数乘次数
					int t = arr[i][k]+arr[k+1][j]+p[i-1]*p[k]*p[j];	 //先计算A[1:k]和A[k+1:n],然后将计算结果相乘得到A[1:n],将三步计算步骤相加即为总计算量
					if(t<arr[i][j]){arr[i][j]=t ; arr2[i][j]=k;}	//保存最小的,即最优的结果
				}
			}
		}
	}
	
	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		int n = s.nextInt();
		int[] p = new int[n + 1];
		for (int i = 0; i < p.length; i++) {
			p[i] = s.nextInt();
		}
		int arr[][] = new int[n+1][n+1];
		int arr2[][] = new int[n+1][n+1];
		
		matrixmultiply(arr,arr2,p,n);
		
		Traceback(1,n,arr2);
	
	}

}




参考 http://blog.sina.com.cn/s/blog_64018c250100s123.html


记第t个矩阵Mt的列数为rt,并令rt-1为矩阵Mt的行数。
MiMk连乘所得是ri-1×rk维矩阵,
Mk+1
Mj连乘所得是rk×rj维矩阵,
故这两个矩阵相乘需要做ri-1×rk×rj次乘法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值