动态规划(DP)

简介: 动态规划(DP)

动态规划(DP)


动态规划,常用于:数学,管理科学,计算机科学,经济和生物信息学。


特征:一个问题,可以拆分成一个一个的子问题,解决子问题,顺带解决这个问题


核心思想:拆分子问题,记住过程,减少重复运算。


例子


1+1+1+1+1+1=? 等于6


在上面式子的再加上一个“ 1+”。答案是多少?


直接通过以往计算过的答案,再加1


例题:青蛙跳阶问题:


一只青蛙,可以一次跳上1级台阶,也可以一次跳上2级台阶。求这只青蛙跳10级台阶有多少种跳法?

分析:

要跳到第10级台阶,要么从第8级台阶,跳2级到第10级。要么从第9级跳1步到第十级。

要跳到第9级:可以从第8级跳1步到达,也可以从第7级跳两步到达。

要跳到第8级:可以从第7级跳1步到达,也可以从第6级跳两步到达。

............


方法一:暴力递归


//暴力递归
//时间复杂度=解决子问题的时间*子问题个数(存在大量重读运算)
public class 青蛙跳阶 {
    public static void main(String[] args) {
        long l1 = System.currentTimeMillis();
        int ways = ways(30);
        long l2 = System.currentTimeMillis();
        System.out.println("有" + ways + "种跳法");
        System.out.println(l2 - l1);
    }
    public static int ways(int n) {
        if (n == 1) {
            return 1;
        }
        if (n == 2) {
            return 2;
        }
        return ways(n - 1) + ways(n - 2);
    }
}


该方法时间复杂度过大,程序运行速度较慢,考虑使用数据字典进行优化


方法二:使用数据字典存储子问题的解(暴力递归的优化)


public class 青蛙跳阶_数据字典优化 {
    public static void main(String[] args) {
        long l1 = System.currentTimeMillis();
        int ways = ways(30);
        long l2 = System.currentTimeMillis();
        System.out.println("有" + ways + "种跳法");
        System.out.println(l2 - l1);
    }
    static Map<Integer, Integer> map = new HashMap();
    public static int ways(int n) {
        if (n == 1) {
            return 1;
        }
        if (n == 2) {
            return 2;
        }
        if (map.containsKey(n)) {
            return map.get(n);
        } else {
            map.put(n, ways(n - 1) + ways(n - 2));
            return map.get(n);
        }
    }
}


方法三:动态规划


动态规划和带字典的递归有些不同,但解法类似。都有减少重复运算。


动态规划的特征:


最优子结构:f(n) = f(n-1) + f(n-2), f(n-1)和 f(n-2)就是f(n)的最优子结构。


状态转移方程:f(n) = f(n-1) + f(n-2)


边界:f(1) =1 ,f(2) = 2


重叠子:重复的运算:f(10) = f(9) + f(8),f(9) = f(8)+f(7). f(8)就是重叠子


public class 青蛙跳阶_动态规划 {
    public static void main(String[] args) {
        System.out.println(ways(10));
    }
    public static int ways(int n) {
        if (n == 1) {
            return 1;
        }
        if (n == 2) {
            return 2;
        }
        int a = 1;
        int b = 2;
        int temp = 0;
        for (int i = 3; i <= n; i++) {
            temp = a + b;
            a = b;
            b = temp;
        }
        return temp;
    }
}


动态规划的解题思路


什么样的问题适用动态规划?


如果一个问题,可以把所有的答案穷举出来,而且存在重叠子问题,就可以考虑使用动态规划。


动态规划的经典应用场景:


最长递增子序列 ---20年蓝肽子问题


最小距离 --- 数字三角形


背包问题


凑零钱问题


等等等。。。


动态规划的解题思路


核心思想:拆分子问题,记住过程,减少重叠子运算


穷举分析


确定边界


找出规律,确定最优子结构


写出状态转移方程


代码实现

目录
相关文章
|
4月前
DP:斐波那契数列模型
DP:斐波那契数列模型
|
11月前
|
决策智能
【dp】背包问题
【dp】背包问题
342 2
|
4月前
[leetcode ~dp ]279. 完全平方数
[leetcode ~dp ]279. 完全平方数
|
人工智能 BI
动态规划(DP)——背包问题
动态规划(DP)——背包问题
|
人工智能
动态规划(DP)——线性DP
动态规划(DP)——线性DP
|
存储 算法
dp 就 dp ,数位dp是什么意思 ?
dp 就 dp ,数位dp是什么意思 ?
320 0
|
算法
【动态规划】使用到dp的题
【动态规划】使用到dp的题
101 0
(闫氏dp分析法)AcWing 2. 01背包问题
(闫氏dp分析法)AcWing 2. 01背包问题
55 0