算法:動態規劃


1.首先來看看維基百科怎麼定義的動態規劃

引自wiki:Dynamic programming

In mathematics, management science, economics, computer science, and bioinformatics, dynamic programming (also known as dynamic optimization) is a method for solving a complex problem by breaking it down into a collection of simpler subproblems, solving each of those subproblems just once, and storing their solutions - ideally, using a memory-based data structure. The next time the same subproblem occurs, instead of recomputing its solution, one simply looks up the previously computed solution, thereby saving computation time at the expense of a (hopefully) modest expenditure in storage space. (Each of the subproblem solutions is indexed in some way, typically based on the values of its input parameters, so as to facilitate its lookup.) The technique of storing solutions to subproblems instead of recomputing them is called "memoization".

Dynamic programming algorithms are often used for optimization. A dynamic programming algorithm will examine the previously solved subproblems and will combine their solutions to give the best solution for the given problem. In comparison, a greedy algorithm treats the solution as some sequence of steps and picks the locally optimal choice at each step. Using a greedy algorithm does not guarantee an optimal solution, because picking locally optimal choices may result in a bad global solution, but it is often faster to calculate. Fortunately, some greedy algorithms (such as Kruskal's or Prim's for minimum spanning trees) are proven to lead to the optimal solution.

For example, in the coin change problem of finding the minimum number of coins of given denominations needed to make a given amount, a dynamic programming algorithm would find an optimal solution for each amount by first finding an optimal solution for each smaller amount and then using these solutions to construct an optimal solution for the larger amount. In contrast, a greedy algorithm might treat the solution as a sequence of coins, starting from the given amount and at each step subtracting the largest possible coin denomination that is less than the current remaining amount. If the coin denominations are 1,4,5,15,20 and the given amount is 23, this greedy algorithm gives a non-optimal solution of 20+1+1+1, while the optimal solution is 15+4+4.


In addition to finding optimal solutions to some problem, dynamic programming can also be used for counting the number of solutions, for example counting the number of ways a certain amount of change can be made from a given collection of coins, or counting the number of optimal solutions to the coin change problem described above.

Sometimes, applying memoization to the naive recursive algorithm (namely the one obtained by a direct translation of the problem into recursive form) already results in a dynamic programming algorithm with asymptotically optimal time complexity, but for optimization problems in general the optimal algorithm might require more sophisticated algorithms. Some of these may be recursive (and hence can be memoized) but parametrized differently from the naive algorithm. For other problems the optimal algorithm may not even be a memoized recursive algorithm in any reasonably natural sense. An example of such a problem is the Egg Dropping puzzle described below.

在文章的 第二段和第三段加黃背景的文字,第二段說明了與貪婪算法的不同並通過第三段的舉例,同一個問題貪婪算法可能會得不到全局最優解,23=20+1+1+1,而動態規劃是23=15+4+4得到全局最優解

還有在wiki Greedy algorithm 中有張圖片:來說明貪婪算法有可能得不到全局最優解,但是幸運的是 Kruskal's or Prim's for minimum spanning trees 達到了全局最優解


2.然後我看  清華大學研究生公共課教材---數學系列---最優化理論與算法(第二版)陳寶林 編著

在最後第16章,以最短路線問題例介紹了動態規劃,並定義了動態規劃中的幾個常用的術語。

1.階段

2.狀態

3.決策

4.策略

5.狀態轉移方程

6.指標函數

7.最優策略和最優軌線

在第二節提出了 R.Bellman的最優性原理:一個最優策略的子策略總是最優的


3. 算法導論中的動態規劃

提到在動態規劃方法的最優化問題中的兩個要素:最優子結構和重疊子問題。

詳細請看 算法導論P202

4.然後看知乎大神的解答

作者:徐凱強
鏈接:https://www.zhihu.com/question/23995189/answer/35324479

動態規劃中遞推式的求解方法不是動態規劃的本質。

我曾經作爲省隊成員參加過NOI,保送之後也給學校參加NOIP的同學多次講過動態規劃,我試着講一下我理解的動態規劃,爭取深入淺出。希望你看了我的答案,能夠喜歡上動態規劃。

0. 動態規劃的本質,是對問題狀態的定義狀態轉移方程的定義
引自維基百科
dynamic programming is a method for solving a complex problem bybreaking it down into a collection of simpler subproblems.
動態規劃是通過拆分問題,定義問題狀態和狀態之間的關係,使得問題能夠以遞推(或者說分治)的方式去解決。
本題下的其他答案,大多都是在說遞推的求解方法,但如何拆分問題,纔是動態規劃的核心。
拆分問題,靠的就是狀態的定義狀態轉移方程的定義

1. 什麼是狀態的定義?

首先想說大家千萬不要被下面的數學式嚇到,這裏只涉及到了函數相關的知識。

我們先來看一個動態規劃的教學必備題:
給定一個數列,長度爲N,
求這個數列的最長上升(遞增)子數列(LIS)的長度.

1 7 2 8 3 4
爲例。
這個數列的最長遞增子數列是 1 2 3 4,長度爲4;
次長的長度爲3, 包括 1 7 8; 1 2 3 等.
要解決這個問題,我們首先要定義這個問題和這個問題的子問題。
有人可能會問了,題目都已經在這了,我們還需定義這個問題嗎?需要,原因就是這個問題在字面上看,找不出子問題,而沒有子問題,這個題目就沒辦法解決。

所以我們來重新定義這個問題:
給定一個數列,長度爲N,
F_{k}爲:以數列中第k項結尾的最長遞增子序列的長度.
F_{1}..F_{N} 中的最大值.
顯然,這個新問題與原問題等價。
而對於F_{k}來講,F_{1} .. F_{k-1}都是F_{k}的子問題:因爲以第k項結尾的最長遞增子序列(下稱LIS),包含着以第1..k-1中某項結尾的LIS。

上述的新問題F_{k}也可以叫做狀態,定義中的“F_{k}爲數列中第k項結尾的LIS的長度”,就叫做對狀態的定義。
之所以把F_{k}做“狀態”而不是“問題” ,一是因爲避免跟原問題中“問題”混淆,二是因爲這個新問題是數學化定義的。


對狀態的定義只有一種嗎?當然不是
我們甚至可以二維的,以完全不同的視角定義這個問題:
給定一個數列,長度爲N,
F_{i, k}爲:
在前i項中的,長度爲k的最長遞增子序列中,最後一位的最小值. 1\leq k\leq N.
若在前i項中,不存在長度爲k的最長遞增子序列,則F_{i, k}爲正無窮.
求最大的x,使得F_{N,x}不爲正無窮。
這個新定義與原問題的等價性也不難證明,請讀者體會一下。
上述的F_{i, k}就是狀態,定義中的“F_{i, k}爲:在前i項中,長度爲k的最長遞增子序列中,最後一位的最小值”就是對狀態的定義。


2. 什麼是狀態轉移方程
上述狀態定義好之後,狀態和狀態之間的關係式,就叫做狀態轉移方程。

比如,對於LIS問題,我們的第一種定義:
F_{k}爲:以數列中第k項結尾的最長遞增子序列的長度.
設A爲題中數列,狀態轉移方程爲:
F_{1} = 1 (根據狀態定義導出邊界情況)
F_{k}=max(F_{i}+1 | A_{k}>A_{i}, i\in (1..k-1))(k>1)
用文字解釋一下是:
以第k項結尾的LIS的長度是:保證第i項比第k項小的情況下,以第i項結尾的LIS長度加一的最大值,取遍i的所有值(i小於k)。

第二種定義:
F_{i, k}爲:在數列前i項中,長度爲k的遞增子序列中,最後一位的最小值
設A爲題中數列,狀態轉移方程爲:
A_{i}>F_{i-1,k-1}F_{i,k}=min(A_{i},F_{i-1,k})
否則:F_{i,k}=F_{i-1,k}
(邊界情況需要分類討論較多,在此不列出,需要根據狀態定義導出邊界情況。)
大家套着定義讀一下公式就可以了,應該不難理解,就是有點繞。

這裏可以看出,這裏的狀態轉移方程,就是定義了問題和子問題之間的關係。
可以看出,狀態轉移方程就是帶有條件的遞推式。

3. 動態規劃迷思
本題下其他用戶的回答跟動態規劃都有或多或少的聯繫,我也講一下與本答案的聯繫。

a. “緩存”,“重疊子問題”,“記憶化”:
這三個名詞,都是在闡述遞推式求解的技巧。以Fibonacci數列爲例,計算第100項的時候,需要計算第99項和98項;在計算第101項的時候,需要第100項和第99項,這時候你還需要重新計算第99項嗎?不需要,你只需要在第一次計算的時候把它記下來就可以了。
上述的需要再次計算的“第99項”,就叫“重疊子問題”。如果沒有計算過,就按照遞推式計算,如果計算過,直接使用,就像“緩存”一樣,這種方法,叫做“記憶化”,這是遞推式求解的技巧。這種技巧,通俗的說叫“花費空間來節省時間”。都不是動態規劃的本質,不是動態規劃的核心。

b. “遞歸”:
遞歸是遞推式求解的方法,連技巧都算不上。

c. "無後效性",“最優子結構”:
上述的狀態轉移方程中,等式右邊不會用到下標大於左邊i或者k的值,這是"無後效性"的通俗上的數學定義,符合這種定義的狀態定義,我們可以說它具有“最優子結構”的性質,在動態規劃中我們要做的,就是找到這種“最優子結構”。
在對狀態和狀態轉移方程的定義過程中,滿足“最優子結構”是一個隱含的條件(否則根本定義不出來)。對狀態和“最優子結構”的關係的進一步解釋,什麼是動態規劃?動態規劃的意義是什麼? - 王勐的回答 寫的很好,大家可以去讀一下。

需要注意的是,一個問題可能有多種不同的狀態定義和狀態轉移方程定義,存在一個有後效性的定義,不代表該問題不適用動態規劃。這也是其他幾個答案中出現的邏輯誤區:
動態規劃方法要尋找符合“最優子結構“的狀態和狀態轉移方程的定義在找到之後,這個問題就可以以“記憶化地求解遞推式”的方法來解決。而尋找到的定義,纔是動態規劃的本質。

有位答主說:
分治在求解每個子問題的時候,都要進行一遍計算
動態規劃則存儲了子問題的結果,查表時間爲常數
這就像說多加辣椒的菜就叫川菜,多加醬油的菜就叫魯菜一樣,是存在誤解的。

文藝的說,動態規劃是尋找一種對問題的觀察角度,讓問題能夠以遞推(或者說分治)的方式去解決。尋找看問題的角度,纔是動態規劃中最耀眼的寶石!(大霧)



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