動態規劃的狀態有時候比較難,不容易表示出來,需要用一些編碼技術,把狀態壓縮的用簡單的方式表示出來。典型方式:當需要表示乙個集合有哪些元素時,往往利用2進製用乙個整數表示。
*:一般有個資料 n<16 或者 n<32 這個很可能就是狀態dp的標誌,因為我們要用乙個int的二進位制來表示這些狀態。要注意好這些資料規模的提示作用。
*:確定了為狀態dp,那麼第一步就是預處理,求出每行所有可能的狀態了,cnt記錄總的狀態數,stk記錄所有的可能狀態。以炮兵陣地為例:
int cnt, stk[max];
void findstk(int n) }
bool ok(int x)
int getsum(int x)
return num;
} *:然後就是dp部分了,明確好狀態轉移方程。先特殊處理第1行,然後按狀態轉移方程求出剩下的值。
經典問題:tsp
乙個n個點的帶權的有向圖,求一條路徑,使得這條路經過每個點恰好一次,並且路徑上邊的權值和最小(或者最大)。或者求一條具有這樣性質的迴路,這是經典的tsp問題。
n <= 16 (重要條件,狀態壓縮的標誌)
如何表示乙個點集:
由於只有16個點,所以我們用乙個整數表示乙個點集:
例如: 5 = 0000000000000101;(2進製表示)
它的第0位和第2位是1,就表示這個點集裡有2個點,分別是點0和點2。
31 = 0000000000011111; (2進製表示)
表示這個點集裡有5個點,分別是0,1,2,4,5;
所以乙個整數i就表示了乙個點集;整數i可以表示乙個點集,也可以表示是第i個點。
狀態表示:
dp[i][j]表示經過點集i中的點恰好一次,不經過其它的點,並且以j點為終點的路徑,權值和的最小值,如果這個狀態不存在,就是無窮大。
狀態轉移:
單點集:狀態存在dp[i][j] = 0;否則無窮大。非單點集:
1:狀態存在 dp[i][j] = min(dp[k][s] + w[s][j])
k表示i集合中去掉了j點的集合,s遍歷集合k中的點並且dp[k][s]狀態存在,點s到點j有邊存在,w[s][j]表示邊的權值。
2.:狀態不存在 dp[i][j]為無窮大。
最後的結果是: min( dp[( 1<
技巧:利用2進製,使得乙個整數表示乙個點集,這樣集合的操作可以用位運算來實現。例如從集合i中去掉點j:
k = i & (~( 1<
動態規劃 狀態壓縮
這個題目的題意很容易理解,在乙個n m的格仔裡,我們現在有兩種型別的磚塊,1 2和 2 1,問一共有多少種方案,可以將整個n m的空間都填滿。最簡單的例子就是下面的了 程式設計之美中題目 某年夏天,位於希格瑪大廈四層的微軟亞洲研究院對辦公樓的天井進行了一次大規模的裝修.原來的地板鋪有 n m 塊正方...
狀態壓縮動態規劃
我們可以使用乙個01串a來表示乙個集合。對於數x x 0 用ax 0表示它不在該集合中,用ax 1表示它在該集合中。將01串a看作是乙個二進位制數,我們把它轉換為十進位制,就可以使用乙個十進位制整數來表示乙個實際使用二進位制方式表示的集合。這樣,我們可以使用位運算方便地處理集合的操作。交集兩個集合a...
動態規劃之狀態壓縮
題目 是hdu 1074,題目大意是說 有幾門課的作業需要做,已知每門課作業的deadline和完成該作業需要花費的時間,求乙個作業的完成順序,使得最終的超時的天數最小。比如,現在如下輸入 computer 3 3 english 20 1 math 3 2 其中,第一列表示課程名,第二列表示dea...