1. 程式人生 > 其它 >動態規劃心得總結

動態規劃心得總結

1. 動態規劃心得總結

1.1. 常規情況的基本步驟

  1. 給出遞推函式定義
  2. 找出遞推函式的遞推關係
  3. 根據遞推關係可以寫出遞迴版本的程式碼
  4. 根據遞推關係可以寫出打表法的動態規劃版本的程式碼

1.2. 給出遞推函式的定義 & 找出遞推關係

基本步驟中的第一步、第二步是緊密關聯的。遞推函式定義的不同會導致遞推關係不同,甚至決定了在這種定義下能否找出對應的遞推關係。當我們確認遞推函式的定義後,那麼其對應的遞迴關係也是確定的、唯一的(如果有的話)。

因此第一步很關鍵,這裡也有些隱藏著的經驗、細活,很多部落格都不會說到,這是我自己思考總結的,包括我看的演算法書上也沒有寫,都是根據題目直接給出了對應的遞推函式定義,然後去論證怎麼去得到遞推關係,沒有講為什麼要這樣定義、是怎樣想到這樣的定義等。

一道題可能有多種遞推函式的定義,但這些遞推函式的有一個共同點就是:變數數量是一定的。

那麼這個維度該怎麼確認呢?總體看,這是一個活的過程,但也有些規律、經驗可以依據。

首先看有幾個輸入,判斷哪些輸入是作為常量,哪些輸入能夠作為變數、或間接的貢獻出變數。比如換錢的方法數,給了兩個輸入,一個是能用的幣值list,一個是要換的錢。我們判斷這兩個值都能作為變數或間接貢獻出變數:對於前者,我們會想到用多少中幣值來計算,對於後者我們會想先從小錢開始,一步一步換到我們給定的錢數。再比如對於機器人到達指定位置的方法數這道題,給定了四個輸入:N表示位置數、M表示起始位置、K表示使用的步數、P表示目標位置。我們可以看到N和M是常量,K、P作為變數。

其次,我們在上一步確定好能貢獻變數的輸入後,還要再選規劃的方法,來確認每個輸入能貢獻多少變數。其實上一步是比較確定的,哪些輸入是規劃過程中的常量,哪些輸入是規劃過程中的變數,是比較明顯的,容易確認的。但是規劃的方法是多變的。一般來說確定在某一個輸入上有幾個在規劃時用到的動點:比如對一個字串來說,一般有兩種選擇:使用兩個動點來表示區間的兩端;使用一個動點來表示區間的一端,然後區間的另一端是固定死的。一個動點就對應的遞推函式定義中的一個變數。

根據上面兩步我們確認遞推函式的維度。但在上面第二步,動點數量依賴於規劃方法的選擇,而規劃方法就直接對應著遞推函式的邏輯定義了。選規劃方法最為關鍵重要,細活都在這。

1.2.1. 選擇規劃方法(重要)

在這一步需要跳出既有思維的約束,就是發現每一類規劃方法中,能變的地方在哪,不同變化的一種組合就是具體的一種規劃方法。

比如:對於字串,我們進行區間規劃的時候,區間有兩端,這時我們面對的兩種選擇:在規劃時,只固定一端,還是兩端都動?如果固定一端的話,是固定哪一段,固定左端還是右端?然後我們還要確認,F(x)表示的是以x位置字元結尾(或開頭)的xxx結果,還是說在【0,x】區間內,不限定以x位置字元結尾的xxx結果?

再比如,對於機器人到達指定位置的方法數,我們是把F(x,y)定義為機器人從位置x走y步到達常量P點的方法數,還是把F(x,y)定義成機器人從常量開始位置走x步到達位置y的方法數?這兩種選擇其實都是可以的。

再比如,對於龍與地下城遊戲中,我們是把F(x,y)定義成從常量開始位置出發到達位置(x,y)所需的最小初始血量,還是說把F(x,y)定義成從變數位置(x,y)出發到達常量終點的所需最小初始生命值?對於這道題前者是行不通的,後者才可以。這就是個固定點選擇導致的可行性與否。

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

在這個過程中要多嘗試,一個錯誤觀念是,從一開始就把自己第一想的到規劃方法用上了,之後把所有時間放在嘗試了去找遞推關係上,就算找不到還是不換規劃方法,然後就一直死磕著。。。

1.3. 根據遞推關係寫出動態規劃版本程式碼

  1. 根據遞推關係中值之間的依賴關係來確認是否能進行矩陣壓縮。(可選)
  2. 首先生成dp矩陣,矩陣的維度數等於遞推函式中的變數數(不包含常量,雖然常量也可能是使用者輸入給出,但它們仍然是常量,不是變數)
  3. 初始化dp矩陣:初始化dp矩陣和遞迴版本程式碼的遞迴終止條件對應,我們初始化dp矩陣主要是填一些邊界值。
  4. 確認返回結果是啥(其實這一步也可以提到前面去)
  5. 根據遞推關係中值與值之間的依賴關係確認打表的順序、方向。
  6. 根據打表的順序、方向、dp矩陣的維度、是否使用矩陣壓縮來寫迴圈。

1.4. 其他

上面說的是常規性的,一般性的步驟流程。但問題是多變的,需要具體分析。

比如:遇到的問題使用上面的步驟搞不定,像最大矩陣系列問題。信封巢狀問題等。
最大矩陣系列問題缺在完全放棄了直觀的建模,生搬硬套常規的做法,信封巢狀問題屬於要先對輸入處理下,然後轉為其他問題的解法。

反正動態規劃都會用到輔助矩陣,輔助矩陣怎麼定義、怎麼用就是展現個人能力的地方,要充分發揮想象。
比如最長遞增子序列一題用到了一個記錄了子序列長度到其結尾最小數對映關係的輔助矩陣,這個很有特色。