(最大矩阵链乘)Matrix-chain product
Matrix-chain product. The following are some instances.
a) <3, 5, 2, 1,10>
b) <2, 7, 3, 6, 10>
c) <10, 3, 15, 12, 7, 2>
d) <7, 2, 4, 15, 20, 5>
矩阵链乘积:
应用动态规划方法:
- 1.刻画一个最优解的结构特征
- 2.递归地定义最优解的值
- 3.计算最优解的值,采用自底向上的方法
- 4.利用计算出的信息构造一个最优解
思想:
1.最优括号化方案的结构特征
用记号A[i..j]表示乘积A[i]A[i+1]..A[j]求值的结果,其中i <=j 。
假设A[i]A[i+1]...A[j]的一个最优解括号把乘积在A[k]和A[k+1]之间分开,则对A[i]A[i+1]...A[j]最优解括号化方案中的“前缀”子链A[i]A[i+1]...A[k]的最优括号化的方法,必须是A[i]A[i+1]...A[k]的一个最有解括号化方案,类似的,A[k+1]A[k+2]…A[j]同理。
2.设m[i][j]为计算矩阵A[i..j]所需的标量乘法运算次数的最小值;
对整个问题,计算A[1..n]的最小代价就是m[1][n]。
假设最优加全部括号将乘积A[i]A[i+1]...A[j]从A[k]和A[k+1]之间分开,i <= k < j。
则:m[i][j] = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]
关于对乘积A[i]A[i+1]...A[j]加全部括号的最小代价的递归定义为:
m[i][j] = 0 if i == j
m[i][j] = min(i<=k<j){m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]} s[i][j]=k if i < j
用s[i][j]记录最优值m[i][j]的对应的分割点。
3.用迭代自底向上的表格法来计算最优代价。
4.利用保存在表格s[n][n]内的、经过计算的信息来构造一个最优解。
按最优方式计算A[1..n]时,最终矩阵相乘次序是A[1..s[1][n]]A[a[1][n]+1..n]。
之前的乘法可以递归地进行。
public class Q1_Matrix_chain { public static int[] atest ={30,35,15,5,10,20,25}; public static int[] a={3, 5, 2, 1, 10}; public static int[] b={2, 7, 3, 6, 10}; public static int[] c={10, 3, 15, 12, 7, 2}; public static int[] d={7, 2, 4, 15, 20, 5}; public static void main(String[] args) { System.out.println("<3, 5, 2, 1,10>"); Matrix_Chain_Order(a); System.out.println("<2, 7, 3, 6, 10>"); Matrix_Chain_Order(b); System.out.println("<10, 3, 15, 12, 7, 2>"); Matrix_Chain_Order(c); System.out.println("<7, 2, 4, 15, 20, 5>"); Matrix_Chain_Order(d); } public static void Matrix_Chain_Order(int[] a){ int n = a.length-1; int[][] m = new int[n+1][n+1]; int[][] s = new int[n+1][n+1]; int i,j,k,t; for (i=0;i<=n;i++) m[i][i] = 0; for (i=0;i<=n;i++) s[i][i] = 0; for(t=2; t<=n; t++) //t is the chain length { for(i=1;i<=n-t+1;i++)//从第一矩阵开始计算,计算长度为t的最小代价 { j = i+t-1;//长度为t时候的最后一个元素 m[i][j] = 1000000;//初始化为最大代价 for(k=i;k<=j-1;k++)//寻找最优的k值,使得分成两部分k在i与j-1之间 { int temp = m[i][k]+m[k+1][j] + a[i-1]*a[k]*a[j]; if(temp < m[i][j]) { m[i][j] = temp; //记录下当前的最小代价 s[i][j] = k; //记录当前的括号位置,即矩阵的编号 } } } } System.out.println("一个最优解为:"); Display(s,1,n); System.out.println("\n计算的次数为:"); System.out.println(m[1][n]); } public static void Display(int[][] s,int i,int j) { if( i == j) { System.out.print('A'); System.out.print(i); } else { System.out.print('('); Display(s,i,s[i][j]); Display(s,s[i][j]+1,j); System.out.print(')'); } } }