矩阵连乘问题–动态规划
题目描述
给定n个矩阵{A1A2…An},其中Ai和Ai+1是可乘的,考察这n个矩阵的连乘积A1A2…An。由于矩阵的乘法满足结合律,故计算矩阵的连乘积有许多不同的计算次序,而不同的计算次序,所需要计算的连乘次数也是不同的,求解连乘次数最少的矩阵连乘最优次序。
例如:
矩阵连乘积A1A2A3,3个矩阵的维数分别为10100,1005和550,连乘时加括号的方式有:
((A1A2 )* A3) 数乘次数:10* 100* 5+10* 5* 50=7500
(A1*(A2*A3)) 数乘次数:100 * 5 * 50+10 * 100 * 50=75000
显然,第一种方法优于第二种。
输入格式:
第一行为一个整数N,表示有N个矩阵;接下来每行分别输入每个矩阵的行数和列数。
输出格式:
输出所计算出的矩阵最小连乘次数。
输入示例:
4
50 10
10 40
40 30
30 5
输出示例:
10500
思路解析:
设计算A[i: j],1≤i≤j≤n,所需要的最少数乘次数m[i, j],则原问题的最优值为m[1,n]。
问题的关键点就在于在哪处进行分割,找出分割点k,然后根据下面公式可以计算出结果:
当i=j时,A[i: j]=Ai,因此,m[i, i]=0,i=1,2,…,n
当i<j 时,m[i,j] = m[i,k] + m[k+1,j] + p(i-1)*p(k)*p(j)
代码如下:
import java.util.Scanner;
public class JuZhenMulti {
/**
* 矩阵连乘问题
* @param p
* @param s
* @param m
*/
static void MatrixChain(int n, int[] p, int[][] m, int[][] s) {
int r,i,j,k,q=0;
for(i=1;i<=n;i++)
m[i][i] = 0;
//r为矩阵链的长度
// r=2时,计算 m[i,i+1],i=1,2,...,n-1 (长度r=2的链的最小代价)
for (r = 2; r <= n; r++) {
for (i = 1; i <= n-r+1; i++) {
//以i为起始位置,j为长度为r的链的末位
j=i+r-1;
m[i][j]=100000000;/*m[i+1][j]+p[i-1]*p[i]*p[j];*/
//s[i][j]=i;
//k从i到j-1,以k为位置划分
for(k=i;k<=j-1;k++)
{
q=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
if(q<m[i][j])
{
m[i][j]=q;
s[i][j]=k;
}
}
}
}
System.out.println(m[1][n]);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in=new Scanner(System.in);
//n为矩阵个数
int n=in.nextInt();
int N=n+1;
int m[][] = new int[N][N];
int s[][] = new int[N][N];
int x=0;
//设置一维数组p用来存放矩阵链,p[0],p[1]为第一个矩阵的行数和列数;p[1]、p[2]为第二个矩阵的行、列数。。。
int p[] = new int[N];
for (int i = 0; i < n; i++) {
p[i] = in.nextInt();
x=in.nextInt();
}
p[n] = x;
MatrixChain(n,p,m,s);
}
}