矩阵链乘法 动态规划

问题描述

输入
• 𝒏个矩阵组成的矩阵链𝑼𝟏…𝒏 =< 𝑼𝟏, 𝑼𝟐, … , 𝑼𝒏 > • 矩阵链𝑼𝟏…𝒏对应的维度数分别为𝒑𝟎, 𝒑𝟏, … , 𝒑𝒏,𝑼𝒊的维度为𝒑𝒊−𝟏 × 𝒑𝒊

输出

• 找到一种加括号的方式,以确定矩阵链乘法的计算顺序,使得最小化矩阵链标量乘法的次数

  • 比如: 3个矩阵相乘 U1(40,8) U2(8,30) U3(30,5)

  • 结合律得到两种不同结合顺序: (U1U2)U3 或者 U1(U2U3)标量乘法次数: 15600 或 2800

解法

//规划方程式 : 从 矩阵 i 得到 矩阵 j 的最小标量乘法次数

D[i,j] = min (D[i][k] + D[K+1,j] + pi-1*pk*pj

在这里插入图片描述

在这里插入图片描述

实际代码

import org.junit.Test;
/**
 * 矩阵乘法问题
 * 递推式 : D[i,j] = min (D[i][k] + D[K+1,j] + pi-1*pk*pj
 *
 * @date 2021-06-10 21:12
 */
public class DP_MatrixMultiplication {
    //测试用例,既:七个矩阵 行高,列长 U1(p0,p1) U2(p1,p2) U3(p2,p3)....
    static int p[] = {2, 3, 7, 9, 5, 2, 4}; 
   //动态数组保存 i到j的最小标量乘法次数
    static int d[][];
    //记录 使用括号对矩阵进行分割的位置
    static int rac[][];
    //矩阵的大小
    static int n;

    @Test
    public void run0() throws Throwable {
        n = p.length;
        d = new int[n + 1][n + 1];
        rac = new int[n + 1][n + 1];
        MatrixChainMultiply();
        System.out.println(d[1][n - 1]);
        PrintMatrixChain(1, n - 1);
        System.out.println();
    }

    private void MatrixChainMultiply() {
        for (int l = 2; l < n; l++) {
            int j = l;
            for (int i = 1; i <= n - l; i++) {
                d[i][j] = 0x7fffffff;
                for (int k = i; k <= j - 1; k++) {
                    int q = d[i][k] + d[k + 1][j] + p[i - 1] * p[k] * p[j];
                    if (q < d[i][j]) {
                        d[i][j] = q;
                        rac[i][j] = k;
                    }
                }
                j++;
            }
        }
    }
	//递归输出 拆分形式
    private void PrintMatrixChain(int i, int j) {
        if (i == j) {
            System.out.print("U" + i);
            return;
        }
        System.out.print("(");
        PrintMatrixChain(i, rac[i][j]);
        System.out.print(")(");
        PrintMatrixChain(rac[i][j] + 1, j);
        System.out.print(")");
        return;
    }
}

输出

286
((U1)((U2)((U3)((U4)(U5)))))(U6) 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值