矩阵连乘问题(动态规划 java)

问题:给定n个矩阵{A1,A2,A3,……,An},其中Ai和A(i+1)是可乘的,i = 1,2,3,……,n-1。考察这n个矩阵的连乘积A1*A2*A3*……*An。

由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同放入计算次序。这种计算次序可以用加括号的方式来确定。若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已经完全加括号,则可依次序反复调用两个矩阵相乘的标准算法计算出矩阵连乘积。


看一个例子,计算矩阵连乘积{A1,A2,A3};维数分别为10*100,100*5,5*50

按此顺序计算需要的次数((A1*A2)*A3):10*100*5+10*5*50=7500次

按次顺序计算需要的次数(A1*(A2*A3)):10*5*50+10*100*50=75000次

所以我们的问题是如何确定计算次序,可以使计算量达到最小化

枚举显然是不可以的,如果枚举的话,相当于一个“完全加括号问题”,次数为卡特兰数,卡特兰数呈指数增长,必然不行


问题的建模:

令m[i][j]表示第i个矩阵至第j个矩阵这段的最优解;

显然如果i=j,则m[i][j]这段中就只有一个矩阵,需要计算的次数为0;

如果i>j,则m[i][j]=min{m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]},其中i<=k<j;

代码实现时需要注意的问题是,注意顺序!!!

因为你要保证计算m[i][j]查找m[i][k]和m[k+1][j]的时候m[i][k]和m[k+1][j]已经计算出来了

import java.util.*;
public class 矩阵连乘问题
{
	public static int n;
	public static int[] p;
	public static int[][] m;
	public static int[][] s;
	public static void main(String[] args)
	{
		Scanner yina = new Scanner(System.in);
		System.out.println("请输入矩阵的个数:");
		n = yina.nextInt();
		System.out.println("请输入矩阵的行数和列数:");
		p = new int[n+1];
		for(int i = 0;i <= n;i++)
		{
			p[i] = yina.nextInt();
		}
		m = new int[n+1][n+1];
		s = new int[n+1][n+1];
		matrixChain(p,n,m,s);
		System.out.println("矩阵连乘的最小次数是:" + m[1][n]);
		System.out.println("矩阵的连乘次序:");
		Traceback(1,n,s);
	}
	public static void Traceback(int i,int j,int[][] s)//递归构造最优解
	{
		if(i == j)
		{
			return ;
		}
		Traceback(i,s[i][j],s);
		Traceback(s[i][j]+1,j,s);
		System.out.println("Multiply A" + i + "," + s[i][j] + "and A" +  (s[i][j]+1) + "," + j);
	}
	public static void matrixChain(int p[],int n,int[][] m,int[][] s)
	{
		for(int i = 1;i <= n;i++)//初始化,矩阵长度为1时,从i到i的矩阵连乘子问题只有一个矩阵,操作次数是0
		{
			m[i][i] = 0;
		}
		for(int r = 2;r <= n;r++)//矩阵的的长度,从长度2开始逐渐边长。
		{
			for(int i = 1;i <= n-r+1;i++)//从第i个矩阵开始,长度为r,则矩阵为(Ai-A(i+r-1))
			{
				int j = i+r-1;
				m[i][j] = m[i+1][j] + p[i-1]*p[i]*p[j];
				s[i][j] = i;//断开点的索引
				for(int k = i+1;k < j;k++)//k从i+1循环找m[i][j]的最小值
				{
					int t = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];
					if(t < m[i][j])//找到比原来的断开点更小的值
					{
						m[i][j] = t;
						s[i][j] = k;//最小值的断开点
					}
				}
			}
		}
	}
}

输入输出:

请输入矩阵的个数:
3
请输入矩阵的行数和列数:
10 100 5 50
矩阵连乘的最小次数是:7500
矩阵的连乘次序:
Multiply A1,1and A2,2
Multiply A1,2and A3,3


  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值