package dynamicDesign;
class Matr {
int a;
int b;
public Matr(int a, int b) {
this.a = a;
this.b = b;
}
}
public class Matrix {
public static void main(String args[]) {
Matr[] matr = { new Matr(3, 2), new Matr(2, 5), new Matr(5, 10),
new Matr(10, 2), new Matr(2, 3) };
int[] a = { 3, 2, 5, 10, 2, 3 };
int s [][] =getBest(a);
traceBack(1,a.length-1,s);
}
public static int[][] getBest(int a[]) {
int n = a.length - 1;// 取得 矩阵的个数
int m[][] = new int[a.length][a.length];
int s[][] = new int[a.length][a.length];
// 初始化
for (int i = 0; i < a.length; i++) {
m[i][i] = 0;
s[i][i] = 0;
}
// 根据矩阵的规模从2个 矩阵到所有矩阵
for (int r = 2; r <= n; r++) {
for (int i = 1; i <= n - r + 1; i++) // i 表示规模为 r 的矩阵的开始位置
{
int j = i + r - 1;// j 表示 规模为 r 矩阵的结束位置
m[i][j] = m[i + 1][j] + a[i - 1] * a[i] * a[j];// 求出矩阵a[i][j]// 的最优值
s[i][j]=i;// 默认为 i 作为最优点
// 因为 m[i][j] i到j 的取值不光有 m[i][i]+m[i+1][j],从i
// 到J的所有位置都有可能,我们要找出来最小的那个
for (int k = i + 1; k < j; k++)// k<j not =, as for m[i+1]
{
int t = m[i][k] + m[k + 1][j] + a[i - 1] * a[k] * a[j];// 从i到j,拆分点在K位置的值
if (t < m[i][j])// 找使m[i][j]最小的K的位置,这个位置就是i~j 矩阵相乘的最小次数
{
m[i][j] = t;
s[i][j] = k;
}
}
}
}
// 打印
/*for (int i = 1; i < m.length; i++) {
for (int j = 1; j < m[i].length; j++)
System.out.print(m[i][j]+ " ");
System.out.println();
}*/
return s;
}
public static void traceBack(int i,int j,int s[][])
{
if(i==j)return ;// i == j 表示 第I个矩阵和第J个矩阵,也就是指同一个矩阵
traceBack(i,s[i][j],s);// i~j 的最优解是s[i][j],再利用相同的方法找出 i ~ s[i][j]
traceBack(s[i][j]+1,j,s);// 同样,找出 s[i][j]+1
System.out.println("A["+i+":"+s[i][j]+"]乘以A["+(s[i][j]+1)+":"+j+"]");
}
}
/*
* 矩阵连乘问题
* |- 0 i == j
* m[i][j ]=
* |- min(n[i][k]+ m[k+1][j]+a[i-1]*a[k]*a[j]) i < j
*
* 思路:
* 1. 确定合适的数据结构,用 m[i][j] 表示子问题最优值,s[i][j] 子问题最优决策
* m[i][j]= k 表示矩阵 i ~ j 最少乘法次数为K,s[i][j] 表示 取得最少乘法的最优点位置
* 2. 初始化,m[i][i] = 0; s[i][i] = 0;
* 3. 因为我们在求多个数组的最优解的时候会用到小个数组的最优解,这也是动态规划 的特点,所以我们先求出
* 小规模的数组的最优解,保存起来,然后再求大规模的数组的最优解
* 如,我们要求m[1][3] 的最优解,我们可以把它拆成m[1][1]~ m[2][3],还可以拆成m[1][2] ~ m[2][3]
* 可见,只要我们先把所有小规模的问题解决了,大规模的也就随着解决了
* 4. 有了上面的分析,我们就成规模为2开始,一直到规模是整个所愿有的矩阵
* for(r=2;r<a.length;r++) 表示了所有的规模
* for(i=0;i<= n - r + 1;i++) 表示了所有的规模为 R 的范围
* {
* 然后根据当前的 i~j 又有多种拆分方式,所以有下面的循环,求最优的点
* for (int k = i + 1; k < j; k++)
* }
*/