算法笔记方法论10 一题详解动态规划解题思路

本文详细解析了如何运用动规方法解决数字三角形问题,包括递归和记忆递推两种形式,重点讲解了如何通过状态转移方程和记忆化来避免重复计算,以及空间优化的实现技巧。涉及的关键概念有最优子结构、无后效性和滚动数组的应用。
摘要由CSDN通过智能技术生成

动规解题的一般思路

1)将原问题分解为子问题

2)确定状态

3)确定一些初始状态(边界状态)的值

4)确定状态转移方程

能用动规解决的问题的特点

1)问题具有最优子结构性质

2)无后效性

动归的常用两种形式

1)递归型

优点:直观,容易编写

缺点:可能会因为递归层数太深导致爆栈,函数调用带来额外时间开销。无法使用滚动数组节省空间。总体来说,比递归型慢。

2)递推型

效率高,有可能使用滚动数组节省空间。

题目29 数字三角形


        3 8
       8 1 0
      2 7 4 4
     4 5 2 6 5

在上面的数字三角形中寻找一条从顶部到底边的路径,使得 路径上所经过的数字之和最大。路径上的每一步都只能往左下或 右下走。只需要求出这个最大和即可,不必给出具体路径。 三角形的行数大于1小于等于100,数字为 0 - 99

输入格式:

5 //三角形行数。

下面是三角形

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

要求输出最大

数组三角形的递归程序:时间复杂度O(2^n)

public class _29数字三角形 {
    static int MAX = 101;
    static int n;
    static int[][] D = new int[MAX][MAX];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i=1; i<=n; ++i) {
            for (int j=1; j<=i; ++j) {
                D[i][j] = sc.nextInt();
            }
        }
        System.out.println(MaxSum(1, 1));

    }

    static int MaxSum(int i, int j) {
        if (i==n) {
            return D[i][j];
        }
        int x = MaxSum(i+1, j);
        int y = MaxSum(i+1, j+1);
        return Math.max(x, y) + D[i][j];
    }
}

数字三角形的记忆递归型动规程序

public class _29数字三角形2 {

    static int MAX = 101;
    static int[][] D = new int[MAX][MAX];
    static int[][] maxSum = new int[MAX][MAX];
    static int n;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i=1; i<=n; ++i) {
            for (int j=1; j<=i; ++j) {
                D[i][j] = sc.nextInt();
                maxSum[i][j] = -1;
            }
        }
        System.out.println(MaxSum(1, 1));
    }

    static int MaxSum(int i, int j) {
        if (maxSum[i][j] != -1) {
            return maxSum[i][j];
        }
        if (i==n) {
            maxSum[i][j] = D[i][j];
        } else {
            int x = MaxSum(i+1, j);
            int y = MaxSum(i+1, j+1);
            maxSum[i][j] = Math.max(x, y) + D[i][j];
        }
        return maxSum[i][j];
    }
}

数字三角形的记忆递推型动规程序

public class _29数字三角形3 {

    static int MAX = 101;
    static int[][] D = new int[MAX][MAX];
    static int[][] maxSum = new int[MAX][MAX];
    static int n;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i=1; i<=n; ++i) {
            for (int j=1; j<=i; ++j) {
                D[i][j] = sc.nextInt();
            }
        }
        for (int i=1; i<=n; ++i) {
            maxSum[n][i] = D[n][i];
        }
        for (int i=n-1; i>=1; --i) {
            for (int j=1; j<=i; ++j) {
                maxSum[i][j] = Math.max(maxSum[i+1][j],maxSum[i+1][j+1]) + D[i][j];
            }
        }
        System.out.println(maxSum[1][1]);
    }
}

空间优化版本

public class _29数字三角形4 {

    static int MAX = 101;
    static int[][] D = new int[MAX][MAX];
    static int n;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i=1; i<=n; ++i) {
            for (int j=1; j<=i; ++j) {
                D[i][j] = sc.nextInt();
            }
        }
        for (int i=n-1; i>=1; --i) {
            for (int j=1; j<=i; ++j) {
                D[n][j] = Math.max(D[n][j], D[n][j+1] + D[i][j]); // 使用滚动数组
            }
        }
        System.out.println(D[n][1]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值