狀壓DP(超詳細!!!)

2022-03-22 11:38:48 字數 3162 閱讀 5878

狀態壓縮動態規劃,就是我們俗稱的狀壓dp,是利用計算機二進位制的性質來描述狀態的一種dp方式。

很多棋盤問題都運用到了狀壓,同時,狀壓也很經常和bfs及dp連用。

狀壓dp其實就是將狀態壓縮成2進製來儲存 其特徵就是看起來有點像搜尋,每個格仔的狀態只有1或0 ,是另一類非常典型的動態規劃

舉個例子:有乙個大小為n*n的農田,我們可以在任意處種田,現在來描述一下某一行的某種狀態:

設n = 9;

有二進位制數 100011011(九位),每一位表示該農田是否被占用,1表示用了,0表示沒用,這樣一種狀態就被我們表示出來了:見下表

所以我們最多隻需要 2^(n + 1) - 1的十進位制數就好(二進位制形式是n個1) 現在我們有了表示狀態的方法,但心裡也會有些不安:上面用十進位制表示二進位制的數,列舉了全部的狀態,dp起來複雜度豈不是很大?沒錯,狀壓其實是一種很暴力的演算法,因為他需要遍歷每個狀態,所以將會出現2^n的情況數量,不過這並不代表這種方法不適用:一些題目可以依照題意,排除不合法的方案,使一行的總方案數大大減少從而減少列舉

為了更好的理解狀壓dp,首先介紹位運算相關的知識。

』&』符號,x&y,會將兩個十進位制數在二進位制下進行與運算(都1為1,其餘為0) 然後返回其十進位制下的值。例如3(11)&2(10)=2(10)。

』|』符號,x|y,會將兩個十進位制數在二進位制下進行或運算(都0為0,其餘為1) 然後返回其十進位制下的值。例如3(11)|2(10)=3(11)。

』^』符號,x^y,會將兩個十進位制數在二進位制下進行異或運算(不同為1,其餘 為0)然後返回其十進位制下的值。例如3(11)^2(10)=1(01)。

』~』符號,~x,按位取反。例如~101=010。

』<>』符號,是右移操作,x>>1相當於給x/2,去掉x二進位制下的最右一位

1.判斷乙個數字x二進位制下第i位是不是等於1。(最低第1位)

方法:if(((1<0) 將1左移i-1位,相當於製造了乙個只有第i位 上是1,其他位上都是0的二進位制數。然後與x做與運算,如果結果》0, 說明x第i位上是1,反之則是0。

2.將乙個數字x二進位制下第i位更改成1。

方法:x=x|(1<

3.將乙個數字x二進位制下第i位更改成0。

方法:x=x&~(1<

4.把乙個數字二進位制下最靠右的第乙個1去掉。

方法:x=x&(x−1)

【例題1】騎士(p1896 [scoi2005]互不侵犯)

題目描述

在 n×n(1<=n<=10) 的棋盤上放 k(0<=k

輸入格式

輸入有多組方案,每組資料只有一行,包含兩個整數 n 和 k。

輸出格式

每組資料一行為方案總數,若不能夠放置則輸出 0。

輸入樣例

3 24 4

樣例輸出

16 79

實際狀壓dp顧名思義,就是採用位運算,來記錄更多的必須記錄的狀態來做dp有了比較深的dp功底後只要對位運算有了解就可以解決問題。。。

考慮到每行每列之間都有互相的約束關係。因此,我們可以用行和列作為另乙個狀態的部分。用乙個新的方法表示行和列的狀態:數字。考慮任何乙個十進位制數都可以轉化成乙個二進位制數,而一行的狀態就可以表示成這樣——例如:1010(2)

就表示:這一行的第乙個格仔沒有國王,第二個格仔放了國王,第三個格仔沒有放國王,第四個格仔放了國王。而這個二進位制下的數就可以轉化成十進位制: 10(10)

於是,我們的三個狀態就有了:第幾行(用i表示)、此行放什麼狀態(用j表示)、包括這一行已經使用了的國王數(用s表示)。

考慮狀態轉移方程。我們預先處理出每乙個狀態(s[x])其中包含二進位制下1的個數,及此狀態下這一行放的國王個數(num[x]),於是就有:

f[i][j][s]=sum(f[i−1][k][s−num[j]]),f[i][j][s]就表示在只考慮前i行時,在前i行(包括第i行)有且僅有s個國王,且第i行國王的情況是編號為j的狀態時情況的總數。而k就代表第i-1行的國王情況的狀態編號

【例題2】牧場的安排(p1879 [usaco06nov]玉公尺田corn fields)

farmer john 新買了一塊長方形的牧場,這塊牧場被劃分成 m列 n 行  (1≤m≤12;1≤n≤12),每一格都是一塊正方形的土地。fj 打算在牧場上的某幾格土地裡種上美味的草,供他的奶牛們享用。遺憾的是,有些土地相當的貧瘠,不能用來放牧。並且,奶牛們喜歡獨佔一塊草地,於是 fj 不會選擇兩塊相鄰的土地,即:沒有哪兩塊草地有公共邊。當然,fj 還沒有決定在哪些土地上種草。 作為乙個好奇的農場主,fj 想知道,如果不考慮草地的總塊數,那麼,一共有多少種種植方案可供他選擇。當然,把新的牧場荒廢,不在任何土地上種草,也算一種方案。請你幫 fj 算一下這個總方案數。

輸入格式

第 1行:兩個正整數 m 和 n,用空格隔開;第 2到 m+1行:每行包含 n 個用空格隔開的整數,描述了每塊土地的狀態。輸入的第 i+1行描述了第 i行的土地。所有整數均為 0 或 1,1 表示這塊土地足夠肥沃,0 則表示這塊地上不適合種草。

輸出格式

第 1 行:輸出乙個整數,即牧場分配總方案數除以 10^8的餘數。

樣例輸入

2 3

1 1 1

0 1 0

樣例輸出

9題目大意

給n*m的棋盤,每個格仔不是0就是1,1代表可以種草,否則不能。相鄰兩個格仔不能同時種草,求種草的方案總數。

思路 狀態壓縮類動態規劃,狀壓dp一般會有明顯的資料範圍特徵,即n,m一般都在20以內。可將每一排的n個看成乙個n位二進位制,先預處理出每一行可以執行的狀態,這樣可以去掉很多無效狀態(如110),然後dp處理,列舉當前有效狀態和上一行有效狀態的關係。

f[i][j] 表示第i行在狀態j的時候的方案數,其中j我們用乙個二進位制數來表示。

轉移的時候只要判斷與當前行和上一行是否衝突即可,如果不衝突,分f[i][j]=∑f[i−1][k]其中k為不衝突的狀態。ans=∑1≤i≤numf[n][i] 就是最後的答案(num為狀態總數)。

初始條件:f[1][i]=1 (1<=i<=a[1].num).

狀壓dp 玉公尺田 狀壓dp

相關 強相關 327.玉公尺田 狀壓dp 小國王 狀壓dp 是井字形,本題是十字形。思路 狀態計算 時間複雜度 n 2 n 2n o n 22n 12 2 24n 2 n 2 n o n2 12 2 n 2n 2 n o n22n 12 224 看著妥妥超時,但是裡面合法狀態很少 依舊可以過 在此,...

狀壓dp小記

鋪磚 題意 現有nm的一塊地板,需要用12的磚塊去鋪滿,中間不能留有空隙。問這樣方案有多少種 include using namespace std typedef long long ll const int maxn 1 11 int n,m,state ll dp 15 maxn s1表示本行...

狀壓dp學習

p2704 炮兵陣地 1038 裁玻璃 狀壓dp是一種非常暴力的做法,列舉所有可能的狀態,找到要求的最佳狀態,與一般dp不同,前一項與後一項有一些複雜的狀態關係。dp的引數 物品個數 行數等 當前狀態 上乙個狀態 將abc的有無表示成乙個8個狀態,列舉所有組,列舉上乙個狀態,得到當前狀態的最優解 i...