package com.duoduo.day316;
/**
* 矩阵连乘问题
* 对于给定 的n个连乘的矩阵,找出一种加括号的方法,使得矩阵连乘的计算量(乘法次数)最少
* @author 多多
*
*/
import java.util.Scanner;
public class Test4_6 {
public static final int msize=100;
public static void main(String [] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入矩阵的个数n:");
int n=sc.nextInt();
System.out.println("请依次输入每个矩阵的行数和最后一个矩阵的列数:");
int [] p=new int[msize]; //记录矩阵的行和列 (行行。。。。列)
for(int i=0;i<=n;i++) {
p[i]=sc.nextInt();
}
int[][] m=new int[msize][msize]; //存放子问题的最优值,记录最小的计算量
int[][] s=new int[msize][msize]; //存储子问题的决策点
matrixChain(m,s,p,n); //矩阵连乘
print(s,1,n); //打印加括号的位置
System.out.println();
System.out.println("最小计算量的值为:"+m[1][n]); //最小的计算量
sc.close();
}
/*矩阵连乘求解函数*/
public static void matrixChain(int[][] m,int[][] s,int[] p,int n) {
//给m[][],s[][]进行初始化 对角线为0
for(int i=0;i<=n;i++) {
m[i][i]=0;
}
for(int j=0;j<=n;j++) {
s[j][j]=0;
}
//处理问题
for(int r=2;r<=n;r++) { //r为问题的规模 r=2为两个矩阵连乘 r=3....r=n
for(int i=1;i<=n+r-1;i++) { //子问题的起点
int j=i+r-1; //子问题的终点
m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j]; //决策为k=i的乘法次数
s[i][j]=i; //子问题的最优策略是i
for(int k=i+1;k<j;k++) { //对从i+1到j的所有决策,求最优值
int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]; //以k作为子问题的划分
if(t<m[i][j]) { //若从位置k处计算量< 子问题
m[i][j]=t; //重新更新最小计算量的值
s[i][j]=k; //更新加括号的划分位置K
}
}
}
}
}
/*最优解输出函数*/
//根据s[][]中的数据构造最优解,即加括号的位置 i==j剩下一个矩阵 则直接打印输出 否则继续划分 递归 依次打印
public static void print(int [][]s,int i,int j) {
if(i==j) {
System.out.print("A["+i+"]");
return;
}
System.out.print("(");
print(s,i,s[i][j]);
print(s,s[i][j]+1,j);
System.out.print(")");
}
}
时间复杂度:
三层for O(n的3次方) print O(n) ----------------O(n3)
空间复杂度:
辅助空间 O(n2)