1. 程式人生 > 其它 >LeetCode之 動態規劃總結

LeetCode之 動態規劃總結

技術標籤:Leetcode遊戲動態規劃演算法javapython

動態規劃

  • 什麼情況下可以用到動態規劃問題(求所有,不用)
    1、求最大值/最小值(從左上角到右上角路徑的最大數字和、最長上升子序列長度)
    2、求方案數(有多少種方式走到右下角、有多少種方法選出K個數使得和是Sum)
    3、求存在性(取石子游戲,先手是否必勝;能不能選出K個數使得和是Sum)

  • 動態規劃四步解題法
    1、確定狀態
    2、狀態方程
    3、初始條件和邊界情況
    4、計算順序

  • 舉例說明解法
    你有三種硬幣,分別面值2元,5元和7元,每種硬幣都有足夠多。買一本書需要27元。如何用最少的硬幣組合正好付清,不需要對方找錢?
    確定狀態:


    1、先看最後一步
    最後一步:存在最後一枚硬幣,an(2、5、7)
    不去關心前面的a1、a2…an-1,只確定前面拼出了27-an
    2、分解為子問題
    如果an是2,f(27)應該是:f(27-2)+1
    如果an是5,f(27)應該是:f(27-5)+1
    如果an是7,f(27)應該是:f(27-7)+1
    狀態方程:
    對於任意x:f[x]=min{ f[x-2]+1,f[x-5]+1,f[x-7]+1}
    初始條件和邊界情況:
    初始條件:設定f(0)=0
    邊界情況:如果不能組合出Y,設定f(Y)=正無窮
    dp[i]=Integer.MAX_VALUE;
    if (i-coins[j]>=0&&
    //錢數大於硬幣數值
    dp[i-coins[j]]!=Integer.MAX_VALUE&&//之前子問題沒有最優解
    dp[i-coins[j]]+1<dp[i])//下一個金額硬幣數量大於上一個
    舉例:1、f(1)=f(1-2)+1=f(-1)+1=正無窮 2、 f(2)=f(2-2)+1=f(0)+1=1
    計算順序:
    可能要考慮,從f(27)、f(26)還是f(1)、f(2)開始呢?
    原則:f(x)=f(x-1)+f(x-2)+…確保,等式右邊都是已知的,計算過的。如果計算f(5)的時候,發現f(3)還沒有計算,那就是錯的。

for (int i = 1; i <dp.length;
i++) { for (int j = 0; j < n; j++) { .... } }

原題:

public static void main(String[] args) {
        int[] coins=new int[]{2,5,7};
        System.out.println(coinChange(coins,59));
    }
    public static int coinChange(int[] coins,int amount){
        //硬幣的數量
        int n=coins.length;
        //換取i元的最小硬幣數量
        int[] dp=new int[amount+1];
        //初始條件
        dp[0]=0;
        //狀態方程
        for (int i = 1; i <dp.length; i++) {
            dp[i]=Integer.MAX_VALUE;
            for (int j = 0; j < n; j++) {
                //邊界條件
                if (i-coins[j]>=0&&//錢數大於硬幣數值
                dp[i-coins[j]]!=Integer.MAX_VALUE&&//之前子問題沒有最優解
                dp[i-coins[j]]+1<dp[i])//下一個金額硬幣數量大於上一個
                    dp[i]=dp[i-coins[j]]+1;
            }
        }
        if (dp[amount]==Integer.MAX_VALUE)
            return -1;
        else
            return dp[amount];
    }

執行結果:
在這裡插入圖片描述