咱們面對的是一個求最優解或統計之類的問題,這個問題基於「咱們要模擬完成一個大任務」,這個大任務能夠分紅若干步驟,每一個步驟有若干種決策,每一個步驟完成後,就到達了一個階段性狀態
好比,你要從A地到Z地,沒有直達,因此第一步須要到一箇中間地點,好比H或I,第二步再前進,好比到P或Q,最後到達Z,每一步有若干決策,好比第一步你能夠決定到H或I的中的某個,大體就是這樣一個模型,能夠本身畫個地圖看看
等等,你大概發現問題了,若是第一步到H和I均可以,第二步到P和Q均可以,那我每一步只選最優,不就用貪心獲得結果了嗎,沒錯,若是你須要經歷的每一個階段狀態跟決策無關,那就貪心獲得結果好了,理解貪心了嗎:)算法
然而現實狀況多是,你第一步的選擇會影響後面的分支,好比你第一步能夠選擇到H或I,可是到了H後,你只能選擇通過P或Q到Z了,而若是到了I,你只能選擇R或S到Z,這樣一來,即使第一步到H或I你選擇了較好的一條路,也不保證最終結果最優,由於好比你選了H,那萬一I-R-Z的路要比H開始到Z的路徑短了更多,最優路徑多是A-I-R-Z,因此你要把這些路都嘗試一遍,才知道哪一個最優,理解窮舉了麼?:)ide
OK,咱們稍微改下題設,假如從I出發不是到R和S,而是到Q或R,會如何優化
誠然,咱們能夠用窮舉每條路來解決這個問題,須要窮舉的路徑數和上面的圖同樣,可是,咱們能夠有更快的辦法,你不用將A-H-Q-Z和A-I-Q-Z兩條路單獨計算,由於他們有狀態交點,結合第一張圖的思想,能夠敏銳地感受到,咱們只須要計算到每一個有共同狀態的位置求各階段的最優,最後每階段選最優組合貪心組合起來就行,由於各階段完成的狀態點是你們都有的嘛,所以,我們先計算A-H-Q和A-I-Q,選個最好的,而後跟Q到Z中最好的拼起來,就是最優了,不必把全部路徑都搞一遍(雖然圖裏面Q到Z直達,但你能夠發揮想象力,將其想象成各類分支的一條複雜道路),這樣一來就把一個x^(a+b+c+...)的計算次數下降爲x^a+x^b+x^c...,其中x表明每次的決策次數(簡單點假設每次決策次數都同樣),abc表明每一個階段的步驟數3d
所以,咱們能夠從A開始,向Z進行BFS,並對BFS中每一個點保存最優狀態,若是有不一樣的路徑BFS到了同一個點,留最好的一條就行,好比上面這個,你的算法可能先從A-H-Q搜到了Q這個位置,以後從A-I-Q又到了這裏,留最好的一條,最後一輪從PQR三個點到Z,就結束了,相對第二章圖要少一次運算blog
若是你理解了,恭喜你已經能有效解決不少須要DP的問題了,同時還學會了解圖論的單源最短路徑問題呢隊列
最後用經典的0-1揹包問題作個例子,鞏固一下吧,這個任務是,咱們從N個物品選若干塞到能夠承受最大重量W的包包裏面,要價值最大,所以就能夠將任務分紅N個步驟,每一個步驟面對第i號物品,決策有兩條:選,仍是放棄,這裏的狀態,就是影響以後步驟決策的因素,在這裏,就是「揹包的剩餘空間」it
好比,物品的重量是1,2,3,4,5,6,W=12,從頭決策,0表示放棄,1表示選,BFS三次後有8種狀態:
000 剩12
001 剩9
……(略)
110 剩9
……(略)
前三次步驟後,001和110到達了一樣的狀態,都是剩餘可裝重量9的東西,這樣在剩下的決策中,這倆分支走的路都是同樣的,跟你以前是選了001仍是110沒有任何關係(無後效性),所以只要看001價值大,仍是110價值大就能夠了,8個狀態減小爲7個,繼續BFS下去,每一輪都合併一樣狀態,完成後,從最後一輪的全部狀態中,找到價值最大的就ok了class
因爲狀態最多有W+1個,進行N輪,所以複雜度O(NW),書上說的狀態遷移方程的辦法其實跟這個過程很相似,不過對於有些題目,比起BFS+狀態合併,狀態方程的分析能夠作更好的優化,如引入單調隊列什麼的,但BFS+狀態合併可讓你獲得一個沒有追求極限可是也比較快的解決方案了,結合具體問題有時候更適合,好比根據問題的實際需求,搜索能夠限界剪枝減小工做量,我在工做中就用過,替換了同事從wiki抄的DP算法,效率能提高一些效率
做者:冒泡
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
搜索