2018過農歷新年這幾天,學了一下狀態壓縮動態規划,現在先總結一下。
狀態壓縮其實是一種並沒有改變dp本質的優化方法,階段還是要照分,狀態還是老樣子,決策依舊要做,轉移方程還是得列,最優還是最優,無后還是無后,所以它比較好理解。
狀壓,顧名思義就是要將一些狀壓想辦法壓縮起來(可以壓,也可以刪)。其中這些狀態都滿足相似性和數量很多。這樣才好壓而且壓得有意義。常見於一般的方格題,網絡題等等。
所以一般基礎的狀壓就是將一行的狀態壓成一個數,這個數的二進制形式反映了這一行的情況。所以位運算可以幫助我們解決很多問題。我看了一篇講義,感覺挺好的,就直接拿來用了,這里會介紹二進制的基本操作和一些常見用法。
這些操作都是在一個數轉成二進制的情況下做的,包括按位與&、或|、取反~(注意負數補碼的符號)、異或^(不同則真)、左移<<、右移>>。
下面是由江蘇省淮陰中學薛志堅整理的一些常見操作:
接下來就是進行普通dp的操作。
不過這里要注意幾點
初試化狀態的時候要看清條件,什么要,什么不要。
一般情況下要預處理前k行(k由題目定)。
Dp時題目給的條件和fit函數、state數組都要檢查。
最最重要的一點:位反(~ ) > 算術 > 位左移、位右移 > 關系運算
> 位與 > 位或 > 位異或 > 邏輯運算
所以一般位運算最好打括號。
講講不常規的狀壓dp。
我們要找一個方法將多余的狀態給砍掉或者縮成一段。
上例題:
1、Corn Fields
最基礎的狀壓dp,很多時候可以用來作為模板借鑒着做其他題目。
詳情請看:這里
2、互不侵犯King
好像是優化搜索,其實還是dp,不過這里比t1的條件多了、難了,也比t1多限定了一個國王數量,所以要多存一個國王數量的狀態,但是其實還是很基礎。
詳情請看:這里
3、炮兵陣地
這里從一個單行狀態變成了雙行狀態,其他都很模板。
詳情請看:這里
4、過河
這是第一道升級的狀壓,它終於不是普通01串的狀態,而是將沒用的狀態給直接砍掉,再進行dp
詳情請看:這里
5、強迫症的炸山
這是我同學(一位大佬)lxy出的題,這道看似很簡短、很簡單的題,做起來卻不是那么容易。我甚至還沒找到怎么正確地壓縮狀態。至今未果,以后會慢慢補充。畢竟現在打暴力得了tle,打正解(手動划去)得了re,我也很無奈。
狀壓dp其實不止這么簡單,我這次學了只是皮毛中的皮毛,狀壓要捉住怎么壓縮狀態,加快程序運行,別的就和普通dp一樣了。
請各位大佬指出錯誤或補充,謝謝。
嗯,就這樣了。