狀壓dp 撲街題解

2022-03-29 14:14:45 字數 1329 閱讀 1257

基礎知識位運算:

1.& 與 x&y表示x和y在二進位制下滿足,每一位有0則0,否則為1的標準進行按位與;

2. | 或 x|y表示在二進位制下每一位按照全0則0,否則為1的標準按位或;

3. ^  異或 x^y 「同為假,異為真」;

4.判斷乙個十進位制數x在二進位制下第i為是否為1 if ( ( ( 1 << ( i - 1 ) ) & x ) > 0)

5.將乙個x進製第i位更換1 x=x|1<

6.把乙個數字二進位制下最靠右的第乙個1去掉 x=x&(x-1)

題目描述:

注意到n,m的範圍比較小,我們要考慮狀壓了,直接搜尋的話:比如我們搜尋每一列,需要記錄上一行每個點的狀態,使用陣列的顯然存不下,所以我們轉變一下思路,採用狀壓+dfs,其實和狀壓dp差不多;

具體怎麼做呢,我們發現,對於每一列,他的狀態只能由上一列的狀態轉移而來,所以我們可以用乙個十進位制數表示當前列的狀態;

dp【i】【s】表示對於放置第i列,第i-1列對他

的狀態是s時的方案數;

對於搜尋,我們不妨將1*2和2*1分開來做,對於第j行,如果j+1可放並且j可放,那我們考慮放乙個2*1的矩陣,那對下一列i+1的影響仍然為ne了;

如果當前j可放,我們也可以考慮乙個1*2的矩陣,那麼對下一列的影響就是ne|(1<

dp[i][s]=∑dp[i-1][k]每乙個k可以通過填放成為s;

對於搜尋,我們只需要對於每一列i,搜尋每一行,並且記錄其對下一列的狀態為ne,判斷狀態是否合法,然後進行深搜就可以了;

#includeusing

namespace

std;

long

long n,m,dp[13][5000

];template

inline void read(t &x)

while(isdigit(ch))

x*=f;

}inline

void dfs(int i,int j,int s,int

ne)

//因為是從第0行開始搜的

if(((1

<0)

if(((1

<0)

if(j+1

1<0&&((1

<

}int

main()

cout

<1][0];//

對m+1列的影響為0表示第m列放滿

return0;

}

view code

感覺說的好不清楚;

狀壓dp題解

實現 includeconst int maxn 1 20 1 typedef long long ll ll f maxn a 25 a x 記錄第x行的障礙狀態 int lowbit int x int main f 0 1 乙個也不放也是一種方案 int maxs 1 判斷當前狀態下狀態的1的...

題解 星空 狀壓DP

這道題思維難度非常高,有很多處理的小技巧,並且 也有很多細節 這道題是一種序列的區間操作,我們都知道,區間操作比較麻煩,所以我們要想辦法將區間操作轉換成單點修改 這時,我們想到了差分,假如我們對乙個序列進行操作,這時乙個序列裡的相對狀態不會變只有兩端改變,換句話說就是這個序列的差分並不會發生改變,只...

題解 Vjestica (狀壓DP)

有n個字元合集,求其字首樹的最少結點個數。資料範圍 n 16,1 m 1000000 字元個數 首先看到 n 16 可知,這道題是狀壓dp或者暴力 狀態是什麼?因為是n的資料範圍小,n為字元合集個數,所以狀態是 n個字元合集的整體 的選擇情況,這裡用s表示,二進位制範圍為 1 11111111111...