談談動態規劃


本篇適合:做了很多動態規劃題了,但是看到微軟這次校招筆試的第二題http://hihocoder.com/problemset/problem/1400 還是很懵逼的同學

其實直到今年5月,我都還是對動態規劃比較懵逼和恐懼的。
刷過很多揹包,刷過LIS、LCS……然而題目稍微複雜一點,秒炸。

果然鵝廠的實習生筆試題來了個 最長迴文子序列 :
然後果然不會做。

之後問學弟,直接甩我一個回答:
這不是區間dp裸題嗎?
dp[i][j]表示從i到j最長迴文子序列的長度。
如果str[i]==str[j] , dp[i][j]=dp[i+1][j-1]+2
否則,dp[i][j]= max (dp[i+1][j] , dp[i][j-1])

這個題之後,突然開始開竅了……

==========================================
就我目前這個渣水平看來,動態規劃的設計,其實不外乎3步:
1、確定基本狀態方式
2、加狀態以能在轉移的時候不受牽制
3、打磨轉移的細節。


第一步是個單選題,就是目前沒見人系統整理過,有選項這一說。

你的轉移過程,從小問題到大問題,你的最小問題要長什麼樣?
01揹包?或者上面提到的微軟的題?從前到後(從第1件,到最後一件)
(其實絕大多數動態規劃起手先試試看從前到後作爲基礎狀態,並沒有大錯)
最優矩陣乘法?從小區間,到大區間(也就是上面提到的區間dp)
在樹上的問題,比如,樹的最遠2點,比如,works application的無線路由器?
以i爲根的子樹作爲狀態(樹形dp)
要枚舉子集?比如,小規模的旅行商問題?
以所有可能的子集作爲狀態(因爲一般用二進制的01表示這個元素在不在子集中,進而把子集這個數學概念/對象,變成一些int範圍內的數值,所以稱作,狀態壓縮動態規劃

等等等等。
(當然還有基礎狀態更加複雜的動態規劃,但這些短期看不會在面試題中出現了,(而且我也不會了),按下不表)

==========================================
至於第二步

曾經有一次個人賽,題目我已經找不到了……
當時那是最後一個題,動態規劃設計感覺黔驢技窮——設計了一種狀態,但是根本沒法轉移,我還要考慮另一個參數——的時候,開始瞎翻手邊的書。
突然看到一句話,豁然開朗:
當發現狀態無法轉移後,常見的方法是增加維度,即增加新的因素,更細緻地描述狀態。
(劉汝佳《算法競賽入門經典(第二版)》)
或者用一些糙的話來講這個道理:
- 誒呀,我做出這個選擇,要看前面做過的選擇的臉色?
- 你要考慮前面什麼東西,就把那個東西加爲狀態
- 誒呀,這裏有個數量/blabla的限制條件?
- 限制條件?轉移過程中控制不能的, 加狀態。

比如上面微軟的那個題:
我從前往後考慮
當前這個字符要不要?要的話還得看前面一個字符???這直接按長度設置狀態,不行啊!
那直接加一維度,表示結束字符啊!這樣你後面轉移不就只要字符沒事就選上,衝突就不作爲轉移來源了嘛~

works application這個題同理:
限制路由器個數?
加一維度狀態,表示用了多少路由器。
我的轉移要看孩子節點的情況(才能算對價值)?
加一維度,表示根節點狀態,這樣父親節點按需拉走。

=======================================================

一句話,dp沒有那麼可怕
找基底,把牽制變狀態,然後?面對面試差不多了,優化再按需考慮吧!

腦子有點亂,當我的胡謅吧,以上。

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