动态规划之矩阵连乘

动态规划算法

代码

import java.util.Scanner;

public class DP {
    public static int matrixChaain(int []p, int [][]m, int [][]s){
        // m[i][j]代表从第i到j之间的矩阵的最小连乘数
        int n = p.length-1;  // 当前矩阵的个数
        for(int i=1;i<=n;i++) m[i][i]=0;  //对角线的值初始化为0,单个矩阵之间自身连乘数为0
        for(int r=2;r<=n;r++)  // r代表连续r个矩阵之间的最小连乘数,之前初始化了1个矩阵之间的连乘,剩余2到n这几种情况
            for(int i=1;i<=n-r+1;i++){  // i代表第i个矩阵 
                int j=i+r-1;  // j代表第j个矩阵
                m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j]; //m[i:j]=m[i:i]+m[i+1:j]
                s[i][j]=i;
                for(int k=i+1;k<j;k++){  // k代表从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;
                    }
                }
            }
            return m[1][n];
    }
    public static void main(String args[]) {
        Scanner scanner=new Scanner(System.in);
        int n=scanner.nextInt();
        int []p = new int[n+1];
        for (int i = 0; i < n+1; i++) {
            p[i]=scanner.nextInt();
        }
        System.out.println("矩阵最小连乘数为:"+matrixChaain(p,new int[n+1][n+1],new int [n+1][n+1]));
    }
}

测试输入

6
30 35 15 5 10 20 25

测试输出

矩阵最小连乘数为:15125

运行结果

image.png

直接递归法

代码

import java.util.Scanner;

public class DG {

    static int[] p;
    static int[][] s;

    public static int recurMatrixChain(int i,int j){
        if(i==j)return 0;
        int u = recurMatrixChain(i+1,j) + p[i-1]*p[i]*p[j];
        s[i][j]=i;
        for(int k=i+1;k<j;k++){
            int t = recurMatrixChain(i,k)+recurMatrixChain(k+1,j) + p[i-1]*p[k]*p[j];
            if(t<u){
                u=t;
                s[i][j]=k;
            }
        }
        return u;
    }
    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        p = new int[n + 1];
        s = new int[n+1][n+1];
        for (int i = 0; i < n + 1; i++) {
            p[i] = scanner.nextInt();
        }
        System.out.println("矩阵最小连乘数为:" +recurMatrixChain(1,5));
    }
}

测试输入

6
30 35 15 5 10 20 25

测试输出

矩阵最小连乘数为:15125

运行结果

image.png

备忘录方法

代码

import java.util.Scanner;

public class BWL {
    static int[] p;
    static int[][] s;
    static int[][] m;
    public static int lookupChain(int i,int j){
        if(m[i][j]>0) return m[i][j];
        if(i==j) return 0;
        int u = lookupChain(i+1,j)+p[i-1]*p[i]*p[j];
        s[i][j] = i;
        for(int k=i+1;k<j;k++){
            int t = lookupChain(i,k)+lookupChain(k+1,j)+p[i-1]*p[k]*p[j];
            if(t<u){
                u=t;
                s[i][j]=k;
            }
        }
        m[i][j]=u;
        return u;
    }

    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        p = new int[n + 1];
        s = new int[n + 1][n + 1];
        m = new int[n + 1][n + 1];
        for (int i = 0; i < n + 1; i++) {
            p[i] = scanner.nextInt();
        }
        System.out.println("矩阵最小连乘数为:" + lookupChain(1, 6));
    }
}

测试输入

6
30 35 15 5 10 20 25

测试输出

矩阵最小连乘数为:15125

运行结果

image.png

实验总结

动态规划的基本思想是,将原问题拆分为若干子问题,自底向上的求解。其总是充分利用重叠子问题,即通过每个子问题只解一次,把解保存在一个表中,巧妙的避免了子问题的重复求解。

递归方法,采用的是自顶向下的思想,拆分为若干子问题,但是造成了子问题的重复求解

备忘录方法,采用的也是自顶向下的思想,但是该方法维护了一个记录子问题解的表,虽然填表动作的控制结构更像递归方法,但是的确避免了子问题的重复求解。相当于解决了使用递归造成的子问题重复求解问题

动态规划算法的基本要素:

1、最优子结构性质:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。
2、重叠子问题性质:动态规划算法对每个问题只解一次,将其解保存在一个表格中,当再次需要解此问题时,用常数时间查看一下结果。因此,用动态规划算法通常只需要多项式时间。

备忘录方法:

•用一个表格来保存已解决的子问题的答案,用的时候查表即可。
•采用的递归方式是自顶向下。
•控制结构与直接递归相同,区别在于备忘录方式为每个解过的子问题建立备忘录。
•初始化为每个子问题的记录存入一个特殊的值,表示并未求解。在求解过程中,查看相应记录如果是特殊值,表示未求解,否则只要取出该子问题的解答即可。

备忘录方法与动态规划和递归的区别:

1、动态规划是自低向上 ,备忘录方法是自顶向下,递归是自顶向下
2、动态规划每个子问题都要解一次,但不会求解重复子问题;备忘录方法只解哪些确实需要解的子问题;递归方法每个子问题都要解一次,包括重复子问题• 。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦码城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值