狀壓dp(總結)狀態壓縮

2022-06-22 11:15:08 字數 1611 閱讀 6315

狀壓這個和二進位制分不開關係

所以,對於二進位制的熟悉是必不可少的技能

&  與操作,1不變,0變0    

|  或操作,0不變,1變1  

^  異或操作,0不變,1取反   

~ 取反操作,把每乙個二進位制位0變1,1變0

還有一些複雜操作可以根據這些去理解

狀態壓縮

所謂狀態壓縮就是把dp的每一次轉移時的狀態用二進位制來表示

或者用二進位制來間接表示

比如這裡有10個蘋果,編號1-10

我拿走了1,4,7,9這四個蘋果

那麼我們可以用011011010這一串二進位制數來表示現在的狀態

0表示這個位置沒有蘋果,1表示有

那麼這就是乙個狀態

相比拿乙個bool型的陣列,這樣表示更方便,記憶體更小,操作更簡單

現在我想把拿走的蘋果放回去,沒拿走的拿走

那麼狀態就變成100100101

直接取反      a=011011010   b=100100101

a==~b;

這時候就充分展示了狀態壓縮的快捷性

下面我們講一道例題。。。。。

在n*n(n≤20)的方格中放置n個車,每個車可以攻擊所在的行和列,求方案總數

直接上排列組合,n!,很好理解啊

在n*n(n≤20)的方格棋盤上放置n 個車,某些格仔不能放,求使它們不能互相攻擊的方案總數。

這時候一些格仔不能放,就要考慮每一行的情況

但是   ,,,,即使每一行中有的格仔不能放,最終還是每一行每一列都要有乙個車子

所以我們用s這個int型的數來表示現在的狀態(行狀態)

如果這一列現在有車子,那這一位就是1

所以最終s一定會變成11111111111(全是1)只有這樣才能把n個車全部放進去

這樣這一狀態有幾個車子說明這就是第幾行

那這樣轉移方程就有了

dp[s]+=dp[s^(s&-s)];

for(;j>0;j-=(j&-j))
還有個問題,有些格仔不能放車

這怎麼辦???????????

還記得前面的蘋果嗎

用1表示這裡能放車子,0表示不可以

在狀態轉移的時候&一下就可以啦

j=i&s[num];
**如下

#include#define ll long long

using namespace std;

int n,m;

long long dp[1<<20];

int s[25];

int main()

j=i&s[num];

for(;j>0;j-=(j&-j))

} printf("%lld",dp[(1這樣基本的狀壓dp就結束了

也許你已經發現了

所有的n都小於等於20

因為int只有32位

這也是狀壓的前提

所以當你一直為空間時間複雜度著急時

就去考慮狀壓

而狀壓前先找到可以狀壓的數

就是32位以內的

狀態壓縮動態規劃(狀壓DP)

狀態壓縮動態規劃就是我們常說的狀壓dp,前兩天某廠實習生二面面試官隨手就給我抽了一道狀壓dp的題,我根本沒思路,sorry就寫了一行注釋。然後leetcode周賽最後一題又碰到了狀壓dp的題目,我一定要搞定這個型別的問題。加油加油 狀壓dp說簡單也簡單,基本上就是用一串二進位制樹來表示當前情況 的狀...

狀壓DP初探 總結

2018過農曆新年這幾天,學了一下狀態壓縮動態規劃,現在先總結一下。狀態壓縮其實是一種並沒有改變dp本質的優化方法,階段還是要照分,狀態還是老樣子,決策依舊要做,轉移方程還是得列,最優還是最優,無後還是無後,所以它比較好理解。狀壓,顧名思義就是要將一些狀壓想辦法壓縮起來 可以壓,也可以刪 其中這些狀...

狀壓DP的總結

狀壓dp的標誌 資料小 通過題目所給出的條件以後得到的特徵集合小 一 cf259div2 d 題目大意 保證b i 中每個數互質,給出a i 然後求1 n的abs a i b i 最小。a i 30 思路 首先得到b i 必然小於60。這個很重要,因為我們列舉的b的集合就是60.首先當b如果都取1,...