输入:先输入矩阵连乘的个数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的行数。
则Mi┅Mk连乘所得是ri-1×rk维矩阵,
Mk+1┅Mj连乘所得是rk×rj维矩阵,
故这两个矩阵相乘需要做ri-1×rk×rj次乘法