第十二章_動態規劃_2019-04-01

動態規劃方法的關鍵點

1、最優化原理,也就是最優子結構性質。這指的是一個最優化策略具有這樣的性質,不論過去狀態和決策如何,對前面的決策所形成的狀態而言,余下的諸決策必須構成最優策略。簡單來說就是一個最優化策略的子策略總是最優的,如果一個問題滿足最優化原理,就稱其具有最優子結構性質。
2、無后效性。指的是某狀態下決策的收益,只與狀態和決策相關,與到達該狀態的方式無關。
3、子問題的重疊性,動態規劃將原來具有指數級時間復雜度的暴力搜索算法改進成了具有多項式時間復雜度的算法。其中的關鍵在于解決冗余,這是動態規劃算法的根本目的。
4、只要能用暴力搜索解決的問題,只要其滿足最優化原理,和無后效性,就可以考慮用動態規劃算法求解

記憶搜索方法和動態規劃方法的聯系

1、記憶搜索就是某種形態的動態規劃方法
2、記憶話搜索方法不關心到達某一個遞歸過程的的路徑,知識單純地對計算過的遞歸過程進行記錄,避免重復的遞歸過程
3、動態規劃方法則是規定好每一個遞歸過程的計算順序,一次進行計算,后面的計算過程嚴格依賴前面的計算過程
4、兩證都是空間換時間的方法,也都有枚舉過程,區別就是動態規劃規定計算順序,而記憶搜索不規定

通過例題來說明動態規劃問題

  • 有value_1、value_2、value_3、……、value_n共n個值,問有幾種能構成數aim的組合方式,其中每個value都能使用多次或不用,Aim大于max(value_1, value_2, value3, ……, value_n)
    本題有三種解決方式,即暴力搜索方法、記憶搜索方法、動態規劃方法,最容易想到的是暴力搜索方法,通過記憶冗余項的方法優化暴力搜索可以得到記憶搜索方法,而記憶搜索方法本質上也是一種動態規劃方法,只不過動態規劃方法在記憶搜索優化策略的基礎上,規定了計算過程中從簡單計算到復雜計算的計算路徑,但是這種優化策略的收獲是與計算路徑無關的,所以記憶搜索方法和動態規劃有相同的時間復雜度,即:O(n * Aim2)
    由于動態規劃規定了從簡單計算到復雜計算的計算路徑,就給動態規劃進一步優化提供的可能,比如在二維的動態規劃問題中dp(value_i, aim)的計算如下:
    dp(value_i, aim) = dp(value_{i - 1}, 0) + …… + dp(value_{i - 1}, aim - 2 * value_i) + dp(value_{i - 1}, aim - value_i) + dp(value_{i - 1}, aim)
    但是dp(value_i, aim - value_i)的值是已經計算過的簡單計算,且正好等于dp(value_(i - 1), 0) + …… + dp(value_(i - 1), aim - 3 * value_i) + dp(value_(i - 1), aim - 2 * value_i) + dp(value_(i - 1), aim - value_i),所以dp(value_i, aim)的值可以化簡為:
    dp(value_i, aim) = dp(value_i, aim - value_1) + dp(value_{i - 1}, aim)
    由于優化后的算法不需要再枚舉很多只,所以動態規劃可以優化為時間復雜度為O(n * Aim)
  • 有n級臺階,一個人每次上一級或者兩級,問有多少種走完n級臺階的方法?
    先列出暴力搜索表達式,其中f(n)表示有n級臺階時的方法數。
    f(i) = f(i - 1) + f(i - 2),且f(1) = 1, f(2) = 2
    然后根據計算過程中的依賴關系來消除冗余,即可得到動態規劃方法
  • 給定一個矩陣m,從左上角到右下角移動,每次只能向下走或向右走一步,路徑上所有數字的累加和為路徑和,返回所有路徑中的最小路徑和
    這道題如果問有幾種方式,就采用組合數來解答,但是要就最小路徑和,這個問題滿足最優化原理,我們可以用動態規劃來解決
    本題為經典的動態規劃題目,如果m的大小為M * N,則創建dp矩陣,行數為M,列數為N。dp[i][j]的指標是從左上角,也就是(0, 0)位置,走到(i, j)位置的最短路徑和。
    dp中第一行的值為m中從第一行第一個位置到dp中當前位置對應的m中位置的所有數的累加和。
    同理,dp中第一列的值為m中從第一列第一個位置到dp中當前位置對應的m中位置的所有數的累加和。
    那么dp[i][j]的計算方法為:
    1、從dp[i - 1][j]向下到達dp[i][j]
    2、從dp[i][j - 1]向右到達dp[i][j]
    3、從1,2中選擇最小的一個再加上當前位置的值就是dp[i][j]的值。
    計算過程中從先從做到右計算一行的值,再從上到下計算下一行的值,最后右下角位置的值即為要求答案
  • 給定數組arr,返回arr的最長遞增子序列長度,比如arr=[2,1,5,3,6,4,8,9,7],最長遞增子序列為[1,3,4,8,9],所以返回這個子序列的長度5*
    解答這道題需要申請長度為n的數組dp,dp[i]表示在必須以arr[i]這個數結尾的情況下,arr[0..i]中的最大遞增子序列長度。
    1、dp[0] = 1
    2、dp[i] = dp[0..i - 1]中所有滿足條件arr[k] < arr[i]的位置k中dp[k]最大的那個數 + 1,即狀態方程為:dp[i] = max(dp[k]+1(0<=k<i,arr[k]<arr[i])),如果沒有滿足條件的k存在則dp[i] = 1
  • 給定兩個字符串str1和str2,返回兩個字符串的最長公共子序列。例如,str1="1A2C3D4B56",str2="B1D23CA45B6A","123456“或者“12C4B6“都是最長公共子序列,返回哪一個都行。
    本題為經典的動態規劃題目,如果m的大小為M * N,則創建dp矩陣,行數為M,列數為N。dp[i][j]表示str1[0..i]和str2[0..j]中的最長公共子序列的長度。
    dp中第一行的值最大值為1,如果dp[0][j] = str1[0],則dp[0][j..N]的值都等于1
    dp中第一列的值最大值為1,如果dp[i][0] = str2[0],則dp[i..M][0]的值都等于1
    那么dp[i][j]的計算方法為:
    1、dp[i][j]可能等于dp[i - 1][j]
    2、dp[i][j]可能等于dp[i][j - 1]
    3、如果str1[i] = str2[j]則dp[i][j]可能等于dp[i - 1][j - 1] + 1
    4、從1,2,3中選擇三種可能之的最大值即可
    計算過程中從先從做到右計算一行的值,再從上到下計算下一行的值,最后右下角位置的值即為要求答案
  • 有一個承重為w的背包,有N件物品,其重量記在重量數組w中,其價值記在價值數組v中,每件物品可能在背包,也可能不在背包,請在不超過背包承重的前提下返回選出物品的最大價值
    這道題和零錢組合問題的不同有:
    1、零錢組合問題中每個面值的前可以使用0~多次,而背包問題中每個重量的商品物品只能用0或1次
    2、零錢組合問題必須達到目標aim,而背包問題不一定要到承重W
    3、零錢組合為題只是返回組合數即可,背包問題中每件物品都有一定的價值,需要返回某所有問題總價值最大的組合
    解決方法:
    創建大小為N * (W + 1)的的dp矩陣,dp[i][j]表示前i件物品在不超過重量j的前提下的最大價值
    dp中第一行的值:如果j >= w[0]則dp[0][j] = v[0],否則dp[0][j] = 0
    dp中第一列的值全為0
    下面枚舉一下dp[i][j]的情況:
    1、如果選中i件物品放入背包,則前i - 1件物品的總重量不能超過j - w[i]
    2、如果不選i件物品進包,則前i - 1件物品的總重量不能超過j
    3、所以dp[i][j]可能等于dp[i - 1][j],也可能等于dp[i - 1][j - w[i]] + v[i],我們從兩種可能性中選擇最大的那個,即:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i])
    計算過程中從先從做到右計算一行的值,再從上到下計算下一行的值,最后右下角位置的值即為要求答案
  • 給定兩個字符串str1和str2,再給定三個整數ic,dc和rc,分別表示插入,刪除和替換一個字符的代價,返回將str1編輯成str2的最小代價
    感覺這道題更像零錢組合問題,同樣一個操作可以用多次,同樣要從一個狀態到另一個狀態,不過此題要求求出最小代價,而不是單純地球方案數
    創建大小為(m + 1) * (n + 1)的矩陣dp,dp[i][j]表示從str1[0..i]編輯到str2[0..j]的最小代價
    dp的第一行的值為插入j個值的累積代價
    dp第一列的值為刪除j個值的累積代價
    dp[i][j]的值可以從如下4個情況來獲得
    1、可能從dp[i - 1][j]的值獲得:dp[i][j] = dp[i - 1][j] + dc
    2、可能從dp[i][j - 1]的值獲得:dp[i][j] = dp[i][j - 1] + ic
    3、當str1[i - 1] == str2[j - 1]時可能從dp[i - 1][j - 1]的值獲得:dp[i][j] = dp[i - 1][j - 1] + rc
    4、當str1[i - 1] != str2[j - 1]時可能從dp[i - 1][j - 1]的值獲得:dp[i][j] = dp[i - 1][j - 1]
    可能性中選擇最小的那個,即:dp[i][j] = min(dp[i - 1][j] + dc, dp[i][j - 1] + ic, dp[i - 1][j - 1] + rc)dp[i][j] = min(dp[i - 1][j] + dc, dp[i][j - 1] + ic, dp[i - 1][j - 1])
    計算過程中從先從做到右計算一行的值,再從上到下計算下一行的值,最后右下角位置的值即為要求答案
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 通過對換錢類題目的學習,我們將了解到 暴力遞歸及優化方法 記憶搜索(優化一) 動態規劃的基本實現方法(優化二) 動...
    周肅閱讀 7,054評論 1 23
  • 動態規劃(Dynamic Programming) 本文包括: 動態規劃定義 狀態轉移方程 動態規劃算法步驟 最長...
    廖少少閱讀 3,338評論 0 18
  • 0. 動態規劃分析 0.1 動態規劃、遞歸和貪心算法的區別 動態規劃就是利用分治思想和解決冗余的辦法來處理問題,所...
    dreamsfuture閱讀 7,485評論 2 6
  • 動態規劃算法一、基本概念動態規劃過程是:每次決策依賴于當前狀態,又隨即引起狀態的轉移。一個決策序列就是在變化的狀態...
    Stephen__Li閱讀 448評論 0 1
  • 今天天氣很好,風很大。 看到風在吹著樹就想到了很多事情。 樹葉里夾雜著斑駁的黃色,就像一個花甲的老人開始生出白發。...
    獨木Atree閱讀 317評論 0 2