动态规划——矩阵连乘

动态规划

动态规划的思想也是把问题分解为规模更小的子问题,跟递归分治的区别在于,动态规划分解得到的子问题不是相互独立的,即动态规划的子问题求解需要依赖于其他的子问题的解,而递归分治得到的子问题求解是相互独立的,不需要依赖于其他子问题的解。在递归与分治中,得到的子问题的解,可能存在一些子问题的计算是相同的,那么就产生了重复计算,浪费了时间,当问题规模逐渐变大的时候,这种重复计算的问题就会被放大,导致时间过长。
在动态规划中,因为在当前的子问题求解中,不知道该子问题的解在之后的计算中需不需要用到,所以要对每一个子问题的解进行保存,然后每当需要用到时,再找出需要用到的子问题的解,这样就避免了对重复子问题的计算,但比起递归与分治,需要腾出地方保存子问题的解,也就是用“空间”换取“时间”。

矩阵相乘

采用标准的矩阵乘法来计算M1、M2和M3三个矩阵的乘积M1M2M3,设这三个矩阵的维数分别是2 × 10、10 × 2和2 × 10。如果先把M1和M2相乘,然后把结果和M3相乘,那么要进行2 × 10 × 2 + 2 × 2 × 10 = 80次乘法;如果代之用M2和M3相乘的结果去乘M1,那么数量乘法的次数为10 × 2 × 10 + 2 × 10 × 10 = 400。显然,执行乘法M1(M2M3)耗费的时间是执行乘法(M1M2)M3的5倍。一般来说,n个矩阵链M1M2……Mn乘法的耗费,取决于n – 1个乘法执行的顺序。请设计一个动态规划算法,使得计算矩阵链乘法时需要的数量乘法次数达到最小,并给出矩阵相乘的先后运算次序,测试算法运行结果时请采用表1所示的矩阵链信息。
链长为6时的矩阵维数示例:
在这里插入图片描述

算法设计思路

给定n个矩阵M1,M2,……,Mn,相邻矩阵可相乘。
①当矩阵只有一个时,乘法次数为0;
②当矩阵只有两个时,只有一种算法,直接相乘;
③当矩阵个数n>2时,对矩阵进行判断:
要构成最少乘法次数的最优解,那么可以先考虑最后一步是在哪个位置进行矩阵相乘,这个位置有n-1种可能性,那么问题就是要找到这n-1种可能性当中的最少乘法次数,设最后一步的位置为k,那么就需要得到该位置前面的矩阵乘法得到的最少乘法结果和该位置后面的矩阵乘法得到的最少乘法结果,这样就需要记录少于n维的的矩阵乘法的最少乘法结果。
计算n个矩阵乘法最少乘法结果,可以用一个n+1的矩阵,前0到n-1个下标记录每个矩阵的行数,第n个下标记录最后一个矩阵的列数,那么,第n+1下标记录的就是第n个矩阵的列数。
创建一个二维矩阵A[n+1][n+1],A[i][j]表示第i个矩阵到第j个矩阵最少乘法次数,新数组每个位置默认为0,即满足A[i][i]=0满足,设置两个for循环,第一个记录此次要计算的矩阵个数,第二个记录开始的矩阵位置,最后得到的A[1][n]就是最终结果。
最后要考虑记录多次乘法的顺序,因为上述过程只记录了次数,因此可以考虑在二维数组A中再增加一个维数,变成A[n+1][n+1][2],第三个维数下标为0时,执行上述操作,下标为1时,记录所得到的断开点的位置k,即得到最少乘法次数的结果后,可以从最后一个k开始递归回去,记录每次得到的两个子问题的k值,这样就得到的次序就是所求的乘法次序的逆序。

算法实现的伪码

函数:matrixMultiply(array, A )
输入:存放矩阵行列数的一维数组array,三维数组A
输出:计算好的三维数组A
S1: for i ← 2 to n//此次计算的矩阵个数
S2: for j ← 1 to n-i+1//计算的第一个矩阵
S3: minSum = MAX//记录最少乘法次数
S4: kk = 0//断点
S5: for k ← j+1 to j+i-1//确定该处断点
S6: nowSum = A[j][k-1][0]+A[k][j+i-1]+array[j]*array[k]*array[j+i]
S7: if nowSum < minSum
S8: then minSum = nowSum
S9: kk = k
S10: A[j][j+i-1][0] = minSum
S11: A[j][j+i-1][1] = kk
S12: return A

算法实现的源码

import java.util.Scanner;
public class Main {
   
	public static void main(String[] args) {
   
		Scanner in = new Scanner(System.in)
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值