動態規劃

動態規劃在一開始學的時候就很迷糊,然後對他很恐懼,一直沒敢弄明白。直到最近要用,所以認真學了一下,理解了一點點,趕緊記下來,防止將來忘掉。
在說動態規劃之前,有一個題目不得不說,那就是斐波那契數列,懂得都懂,如果要找一個通式的話,那就是:f(n) = f(n - 1) + f(n - 2) ;f(1) = f(2) = 0;第一個數和第二個數是1,以後每個數是前面兩個數之和。爲什麼說動態規劃之前要說斐波那契數列呢,這時因爲動態規劃和斐波那切數列有一定的相似性,斐波那切數列是兩個數之和,而動態規劃是從兩個書中選最優的那一個。
我們可以看一道題目:

a = [10,1,2,7,6,1,5], target = 8,
在a數組中能不能找到一組數,它們的和是target 8。

用動態規劃解決這道題,可以這樣想:a數組一共有7個數,我們只需要知道前七個數中有沒有一組數之和等於8(這不廢話嗎,別急,爲了隊形)

  • 第一層:前7個數中有沒有一組數之和等於8,這時有兩種可能,第七個數在這一組數中,第七個數沒在這一組數中。
  • 第二層:
    • 第七個數在這一組數中,現在我們需要知道前六個數中有沒有一組數之和等於3(8 - 5 = 3)
    • 第七個數沒在這一組數中,現在我們需要知道前六個數中有沒有一組數之和等於8(8 - 0 = 8)
    • 第二層總結:現在我們就從“前七個數中有沒有一組數之和等於8”,分裂出兩個子問題“前六個數中有沒有一組數之和等於3”和“前六個數中有沒有一組數之和等於8”
  • ………………

如此往下推,雖然問題的數量變多了,但是有沒有發現,如果寫出通式,會和斐波那切數列的類似。
我們把前n個數中有沒有一組數之和等於target設爲f(n,target) ,就可以寫出這樣的式子:

f(n,target) = f(n - 1,target - a[n]) || f(n - 1,target)

也就是隻要f(n - 1,target - a[n]) 和f(n - 1,target)只要有一個爲真f(n,target)就爲真。
如此一直求下去,一直求到我們一開始就知道值的位置(出口),然後回溯,便可以求出f(n,target)的值,那麼出口在哪呢,這一道題一共有三個出口:

  • 首先當然是使式子成立的出口,當求着求着發現a[n]等於target的時候,就說明後面的已經滿足條件了,不需要繼續向前找了,這時返回真即可
  • 然後是式子不成立的出口,一種是target大了,求到第一個數,發現數組裏的數全要了,和還是小於target,顯然式子不成立,返回假
  • 另一種是target小了,在某一次求值的時候,如果選擇數組中的這個數,會使target變成負數,要從前面找出一組數之和爲負數(本題數組的數全是正數),這顯然不可能,這也是個出口,式子不成立,返回假

這三個出口,實際包含了所有將式子求到最後可能的情況,有了它們,便可以解答題目。

這還沒完,如果僅僅這樣做,我們想一下,第二層分出兩條路,第三層分出四條路,第四層的時候分出了8條路,這8條路都要計算前4個數有沒有一組數等於target,這裏的target可能相等(這道題效果不明顯),如果相等,就會做重複的計算,大大增加時間複雜度,因此,用適當的數組標記一下,用空間複雜度換時間複雜度,例如:book[n][target] = true/false;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章