轉【算法之動態規劃(五)】DP規劃思想學習:從《算法導論》到《算法設計》

像全部的新手同樣,對一種算法思想的理解須要經歷從膚淺(流於表面形式)到逐漸觸摸到本質的過程。爲何說逐漸觸摸到本質,是由於不少時候你並不肯定一個解釋是否是最本質的,有時候會有好幾個等價的解釋,各自在不一樣的場景下具備。

  動態規劃經典題集轉]動態規劃與排列組合,好比對動態規劃(DP)的理解,一開始我理解爲遞推,但實際上這是最膚淺的理解,對於如何在特定的問題中找到遞推關係毫無幫助和。換言之,這只是一個描述性的總結,而不是一個建設性的總結,不含方。

  作(看)了一些題目以後我開始總結關於How的方法,怎樣尋找到遞推關係(遞推關係蘊含着子問題)。獲得一個簡單的觀察,若是一個問題裏面含有n這個變量,考慮把n變成n-1的狀況。

  固然,這個方法常特殊(狹窄)的。實際上更具通常性的方法是不只能夠從n-1後面切一刀,還能夠在任意地方切(譬如切成兩個n/2規模的),以任意標準切(好比像快排那樣的)。全部考慮各類切法中哪一種可以最有利於創建子問題是有幫助的。

  這個我姑且把它叫作經過直接切分問題來尋找子問題。

  但是。這仍是特殊了。由於顯然這個方法不能解決全部的DP問題,連多數DP問題都未必能解決。譬如你們熟悉的最大(小)和連續子序列問題,就難以經過這種方法求解(可行,但思惟難度較大。);再譬如上次Lee給的敲石頭問題,以及DD出的不聽話的機器人問題。所以,在知道了這幾個問題的解法以後我繼續思考這些解法裏面是否是蘊含着更具通常性的解題方法。

  看起來我找到了一個,就是分類討論法,具體作法是:首先,寫出可行解的通常形式,譬如a1,a2,...,an。而後對其中的某個不肯定的ai進行討論。譬如旅行商問題裏面對下一個城市進行討論。當不肯定時,討論。討論的每一個分支都帶來了進一步的肯定性,從而將問題成一個子問題。

  而後Lee提到,這個方法是自頂向下的,有時候不適于思考,譬如對敲石頭問題。並提到一種自底向上,着重於構造狀態的外推法。

  因而,到目前爲止,DP的通常性式思考方法就已經有了三種:

  1.經過直接對問題切分來探索子問題。

  3.經過創建狀態來自底向上地推導最終解。

  但是,我內心仍是不踏實,由於離散的知識是極其不利於記憶的,須要更多的才能在運用的時候情不自禁的聯想起來,並且也容易遺忘。每次作DP題的時候,我都得把好幾種指導性的思一一費勁從腦殼裏翻出來,而後嘗試。實在很不爽。雖然DP題也許並無萬用的解題手法,但我仍是但願可以儘可能提取出不一樣手法之間的本質聯繫,若是可以將一組看上去離散的知識點統一在一個更具通常性,更本質的知識點下面,咱們的知識樹就多出了一個根節點,因而下次提取的時候只要提取出那個根節點,下面的幾個子節點就會一一乖乖閃現,極大的下降記憶的複雜性。

  那麼,三種手法的本質聯繫究竟是什麼呢?有一次在上走的時候我想出了一種解釋。它也許不是最本質的,也許大牛們早就想到過,可是我以爲至少有兩個好處:

  1.它涵蓋以上三種手法,經過增長一個根節點,減小知識的記憶複雜性和易提取性。

  2.概括抽象的過程自己就是一種鍛鍊,鍛鍊的是概括抽象的能力。

  動態規劃經典題集這個解釋就是:大多DP問題的可行解的形式是一個排列組合(典型的——旅行商問題、最短徑問題)。你們都知道,窮舉一個規模爲N的排列組合複雜性是a^n的,也就是組合複雜性。而求解DP問題的核心步驟:發現「子問題」,這個「子問題」實際上就是對應最終解的那個排列組合的某個子排列組合(某種子集);而這裏的「子排列組合」的數目則每每是多項式的(silwile,,指出並不是老是如此),這就是爲何一個組合複雜性的窮舉問題能夠DP 優化爲多項式複雜度的問題。將重複出現的子排列組合對應的子問題的解緩存起來,就是DP的緩存優化了。

  此外,這一解釋也提供瞭如何探索子問題的一個通用方案:尋找形式相同的子排列組合。仍是拿最大和連續子序列說事,其解的形式是:A[i],A[i+1],..,A[j-1],A[j],其中i,j不肯定。那麼如何獲得形式相同的子組合呢?首先討論A[j],爲何要討論,由於只要A[j]不肯定,A[j-1]就不肯定,就拿不出子組合來。對於一個肯定的A[j0],解的可能性爲A[i],A[i+1],..,A[j0-1],A[j0]。其最優解依賴於子組合 A[i],A[i+1],..,A[j0-1],到這裏子問題就不請子現了:A[i],A[i+1],..,A[j0-1],A[j0]和 A[i],A[i+1],怎麼開通騰訊圖書如何在微時代打造出一本暢銷書..,A[j0-1]的形式相同,意味着它們是同一個問題的不一樣階表示。

  固然,因爲這個指導思想通常性大了點,因此實際問題中每每沒有前面提到的三種手法尋找方案來得快——衆所周知的是,越特定的手題面雖然越窄,但若是題目對口瞭解決起來也越快。但它至少有兩個好處(前面說過了)。因此考慮通常性和特殊性的手法都是有幫助的。

  相似的,敲石頭問題也能夠經過這種手法來探索子問題。至少目前我作過的DP題彷佛均可以藉助這種手法來探索,固然,剛纔說過了哈7》驚險二連冠 《格列佛遊記》,未必是最快的,因此也許能夠考慮用來作後備方案,當其它方案沒有頭緒的時候試試。

  個人解題經驗還頗有限,因此不清楚這個手法的覆蓋範圍有多廣。實際上一個更廣的領域是組合優化。更提到的很像。但針對的問題就不只止於DP了。

  你說得沒錯。用空間換時間是DP的一個重要性質,事實上,它仍是許多算法的一個性質。因此說,「用空間換時間」並無「充分」地描述DP的特色,更沒有對「如何探索一個DP問題的解」提供建設性的幫助。對於後者,如何尋找遞推關係或「子問題」纔是重點,一旦找到了子問題以後經過緩存子問題的解來優化複雜度就相對比較trivial了。

  DP的思想理解起來容易,一開始的時候我看了幾本書的DP章節,以爲,哦,這很容易,遞推嘛。但真正本身作題的時候,發現尋找遞推關係是最困難的一步,non-trivial的DP題裏面遞推關係並非顯而易見的。

  TopLang裏面也有人推薦《算法藝術與信息學競賽》,但提到裏面的題目偏難,不適合初學者。做爲題集應該仍是不錯的。聽說幾本衆所周知的經典算法書裏面最適合程序員學習的是《AlgorithmDesign》,如下引一段g9的介紹:

  我也喜歡AlgorithmDesign這本書。我的以爲很是適合初學者和程序員。書一開始就給出穩定婚姻問題。從解決問題的角度入手,層層遞進地怎麼設計,引出算法設計的通常方法。而後用幾道常見題目引入經常使用算法的設計思。奠基總綱後,後面的書就從不一樣的角度深化算法設計的方法。例題也有趣。我的至關喜歡從設計到分析的思。這種方法給讀者(至少是程序員)誘人的動機。畢竟不少人讀算法書是爲了寫出更強大的程序。尤爲像我這種老人家,NADD症狀嚴重,尤爲須要使人信服的動機,否則就老走神。並且做者強調設計,反而提供了鑽研算法分析的充分理由,很好地解釋了要設計出正確高效的算法,形式化的分析是必要手段。爲什要擴展?爲何要處處一堆引理?爲何要追究複雜度?爲何要泛化?爲何要特化?這些看來學究的行爲天然地有了現實基礎。加上這本書寫得曉暢通透,就算你只看書不動手,也能夠得到好舒服,原來我也能夠設計出這些算法啊。一點都不難嘛這種相似後的波浪狀快感和。:-D

  DP的思想理解起來容易,一開始的時候我看了幾本書的DP章節,以爲,哦,這很容易,遞推嘛。但真正本身作題的時候,發現尋找遞推關係是最困難的一步,non-trivial的DP題裏面遞推關係並非顯而易見的。[/quote]

  又碰到一個有上思考習慣滴。我想做者想描述的本質可能在於,如何識別一個問題是DP能夠用DP解決的,因此順着這種想法,天然就像探究DP的本質,由於一旦探究了DP的本質就能夠迅速的對須要解決的問題進行定位,而後解決。好比一個很難的題目,咱們告訴應試者能夠用DP解決,也許他很快能想到答案,若是咱們不說呢,也許他搞不定。認清DP的本質就有助於咱們判斷某個問題是否用DP能夠解決,我想這是樓主的本意吧。raymond程序員

 

來源:http://blog.csdn.net/cangchen/article/details/45045633算法

相關文章
相關標籤/搜索