《算法導論》之分治策略與動態規劃

  • 分治策略
      分治策略是一種很重要的算法思想,不少不少問題均可以用分治策略解決。好比排序,漢諾塔以及一些最優化問題等等
      分治策略的意義就是將複雜問題還原成簡單問題解決掉,且這些簡單問題具備某些共同邏輯。
      遞歸實現的代碼會很簡潔,邏輯也會簡單些,但複雜度分析就難了,通常要用到組合數學的知識
      但書中給了一種叫作「主方法」的通用式求解方法
      設遞歸方程 T(n)=aT(n/b)+f(n) 其中a>=1,b>1是常數,f(n)>0
      其意義是將T(n)的n規模的問題轉化成a個T(n/b)規模的小問題,中間可能還須要一些輔助計算,就是f(n)
      那麼
  
       具體細節我很少說,感興趣的能夠看書,這個東西主要是拿來快速評估的
  • 動態規劃
   動態規劃的大名我很早就聽過,但一直不知道是什麼。本科的時候還上過運籌學的。
       線性規劃我到知道,看了書之後,我以爲動態規劃頗有用,很是有用。
       動態規劃和分治策略類似,不一樣的是,它針對的問題所分解出的小問題數量不少且不少是重複的。
       動態規劃就是使得這些重複的小問題只須要計算一次,避免重複計算。
 
       鋼條切割問題:給定一段長度爲n英寸的鋼條和一個價格表pi(i=1,2,...,n)求切割鋼條方案,使得銷售收益rn最大。
    注意,若是長度爲n英寸的鋼條的價格p n足夠大,最優解可能就是徹底不須要切割。
       思路:先將鋼條切成兩條,有n-1種方案,每一種方案的最優解都等於兩個子鋼條的最優解。咱們從這n-1個僞最優解再挑出最優的解了
       如下是僞代碼:
1 CUT-ROD(p,n)
2 if n == 0
3     return 0
4 q=負無窮
5 for i = 1 to n
6     q=max(q,p[i]+CUT-ROD(p,n-i))
7 return q

上面只用了分治策略,這個算法的性能是不好的T(n)=2n,在子問題的求解中不少都是重複的。算法

動態規劃就是避免這些重複。通常有兩個思路1.記錄中間解 性能

 1 MEM-CUT-ROD
 2 let r[0..n] be a new array
 3 for i = 0 to n
 4     r[i]=負無窮
 5 return MEM-CUT-ROD-AUX(p,n,r)
 6 
 7 MEM-CUT-ROD-AUX(p,n,r)
 8 if r[n]>=0
 9     return r[n]
10 if n==0
11     q=0
12 else q=負無窮
13     for i=1 to n
14         q=max(q,p[i]+MEM-CUT-ROD-AUX(p,n-i,r))
15 r[n]=q
16 return q

 2.經過對問題求解順序的合理安排,達到避免重複優化

1 BOTTOM-UP-CUT-ROD(p,n)
2 let r[0..n] be a new array
3 r[0]=0
4 for j=1 to n
5     q=負無窮
6     for i=1 to j
7         q=max(q,p[i]+r[j-i])
8     r[j]=q
9 return r[n]

 

是否是很帥,反正我以爲很帥。i<=j, j>j-i>=0
後面有個更帥的,前面這兩個算法都只給出了最優收益,沒有返回解自己。
 1 EXTEND-BOTTOM-UP-CUT-ROD(p,n)
 2 let r[0..n] and s[0..n] be new arrays
 3 r[0]=0
 4 for j = 1 to n
 5     q=負無窮
 6     for i =1 to j
 7         if q < p[i]+r[j-i]
 8             q=p[i]+r[j-i]
 9             s[j]=i
10             r[j]=q
11 return r and s
12 
13 PRINT-CUT-ROD-SOLUTION(p,n)
14 (r,s)=EXTEND-BOTTOM-UP-CUT-ROD(p,n)
15 while n >0
16     print s[n]
17     n=n-s[n]

動態規劃真的是個好東西,書中還講了動態規劃在最長公共子序列以及最優二叉搜索樹上的應用,此處不細講。spa

使用動態規劃方法求解的最優化問題應該具有兩個要素:最優子結構和子問題重疊。code

相關文章
相關標籤/搜索