狀態壓縮動態規劃入門篇

2021-07-04 05:38:48 字數 1236 閱讀 9586

狀態壓縮動態規劃

動態規劃的狀態有時候比較難,不容易表示出來,需要用一些編碼技術,把狀態壓縮的用簡單的方式表示出來。典型方式:當需要表示乙個集合有哪些元素時,往往利用2進製用乙個整數表示。

*:一般有個資料 n<16 或者 n<32 這個很可能就是狀態dp的標誌,因為我們要用乙個int的二進位制來表示這些狀態。要注意好這些資料規模的提示作用。

*:確定了為狀態dp,那麼第一步就是預處理,求出每行所有可能的狀態了,cnt記錄總的狀態數,stk記錄所有的可能狀態。以炮兵陣地為例:

*:然後就是dp部分了,明確好狀態轉移方程。先特殊處理第1行,然後按狀態轉移方程求出剩下的值。

int cnt, stk[max];

void findstk(int n)

return num;

}

經典問題: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<

動態規劃入門篇

動態規劃相信大家都知道,動態規劃演算法也是新手在剛接觸演算法設計時很苦惱的問題,有時候覺得難以理解,但是真正理解之後,就會覺得動態規劃其實並沒有想象中那麼難。在上面的數字三角形中尋找一條從頂部到底邊的路徑,使得路徑上所經過的數字之和最大。路徑上的每一步都只能往左下或 右下走。只需要求出這個最大和即可...

教你徹底學會動態規劃 入門篇

動態規劃相信大家都知道,動態規劃演算法也是新手在剛接觸演算法設計時很苦惱的問題,有時候覺得難以理解,但是真正理解之後,就會覺得動態規劃其實並沒有想象中那麼難。網上也有很多關於講解動態規劃的文章,大多都是敘述概念,講解原理,讓人覺得晦澀難懂,即使一時間看懂了,發現當自己做題的時候又會覺得無所適從。我覺...

楊輝三角高階(動態規劃入門篇)

給定乙個非負索引 k,其中 k 33,返回楊輝三角的第 k 行。示例 輸入 3 輸出 1,3,3,1 高階 你可以優化你的演算法到 o k 空間複雜度嗎?使用乙個指定行數加一容量的陣列,就是指定行的元素個數。從第0行開始,把楊輝三角的改行資料放入到這個陣列中。我們只關心最後一行,所以這個陣列是可以重...