明天計畫上是要刷狀壓,但是作為現在還不會狀壓的\(ruoruo\)來說是一件非常苦逼的事情,所以提前學了一下狀壓\(dp\)。因為剛學習狀態壓縮,並且剛做完一道例題。寫部落格的主要目的是怕自己忘掉,免得以後再重新學習一遍。而那些來踩我部落格的同志們,希望以辯證的眼光來看待這篇博文。鳴謝\(hmq\ juju\)的友情幫助
於是這篇部落格就講\(corn fields\)
這一道例題。所以閱讀以下內容之前請先瀏覽一下題目。
狀態壓縮\(dp\)主要是在二進位製上進行狀態轉移的一種動態規劃,因為每乙個十進位制的數可以表示成二進位制,所以我們每一行的狀態用乙個十進位制的數來儲存。
因為狀態是在二進位製上進行轉移的,所以我們需要用到一些位運算來幫助我們進行狀態轉移。
首先列舉所有的情況。根據題意,\(1\)表示有草,\(0\)表示沒草,然後又有\(n\)位,所以我們就列舉\(0\sim2^n\)的位數,為啥尼?
因為\(0\)表示沒有草的情況,而\(2^n\)也就是\(\begin \underbrace \\ n\end\)這種全是草的情況,所以要這樣列舉。然後我們在儲存合法狀態,存到\(state\)陣列裡。
列舉完之後,我們的所有情況出來了,我們要進行存圖,存圖也要用二進位制。這裡我們存圖用乙個\(cur\)陣列,這個陣列表示圖的儲存,為了方便,我們將無草轉變為\(1\),有草為\(0\)。
然後就是進行狀態儲存。我們已經有了合法狀態,我們也有圖,我們就要列舉判斷合法狀態內的可行狀態。
這裡我們要用到乙個\(fit\)函式。fit函式可以幫助我們判斷合不合理,然後找到可行狀態
狀態轉移。設\(dp[i][j]\)表示第\(i\)行的第\(j\)個狀態。
狀態轉移要列舉上一層的狀態。然後方程很簡單\(dp[i][j]=dp[i][j]+dp[i-1][k]\)。
inline void init()//初始化
為啥是左移\(n-j\)為呢\(?\)
因為你是從右往左來儲存二進位制的,第\(j\)位如果反過來肯定是第\(n-j\)位咯。
inline bool fit(int x,int k)//判斷當前狀態是否符合當前行
只要這乙個函式理解了,狀壓就基本搞定了。
因為\(state\)儲存的是合法狀態,\(cur\)儲存的是不合法狀態,所以兩者按位與,合法狀態的數一定為\(0\),不合法狀態的數一定不為\(0\)。這裡有的同志就開始疑惑了,為啥尼?
你想想\(state\)裡面\(1\)為有草,\(cur\)裡面\(1\)為無草,而\(1\&1\)則代表有值,那麼這個方案可行嗎?
就這樣我們能進行第一行的初始化咯
for (i=1;i<=tot;i++)//初始化第一行
if (fit(i,1))
dp[1][i]=1;
狀態轉移相對來說就比較簡單了。
for (i=2;i<=m;i++)//枚舉行
for (j=1;j<=tot;j++)//列舉當前狀態
}
具體可能的疑問都在**中注釋了
第一層枚舉行數,第二層列舉可行方案,第三層列舉上一層的可行方案,萬事大吉!
#include#include#include#define mod 100000000
#define c continue//懶得打hhhhh
using namespace std;
int n,m,tot,state[1500],dp[15][1500],ans,cur[15];//dp表示當前最大值,第一維是行數,第二維是狀態數,cur是每行的情況,state是預存的可能狀態
inline int read()//讀入優化
inline bool fit(int x,int k)//判斷當前狀態是否符合當前行
inline void init()//初始化
int main()
for (i=1;i<=tot;i++)//初始化第一行
if (fit(i,1))
dp[1][i]=1;
for (i=2;i<=m;i++)//枚舉行
for (j=1;j<=tot;j++)//列舉當前狀態
}for (i=1;i<=tot;i++)
ans=(ans+dp[m][i])%mod;
printf("%d",ans);
return 0;
}
狀態壓縮DP
首先,我們以一道狀壓經典題tsp來引入。tsp問題 一張圖上有n個點,給定相應的鄰接矩陣,需要求出從0號節點出發,經過且只經過每個頂點一次,最後仍回到0號節點的最小邊權。思路 假設現在已訪問過的頂點集合 起點0當作還未訪問過的頂點 為s,當前所在頂點為v,用dp s v 表示從v出發訪問剩餘的所有頂...
狀態壓縮DP
theme 給定乙個n m的玉公尺田,1 n,m 12。值為0表示不能在該塊種草,為1表示可以。現在要在其上中若干草地,要求任意草地間不相鄰 沒有公共邊 問不考慮草地個數的情況下,有多少種種植的方案?solution 用dp。又範圍很小,所以考慮狀態壓縮dp,另dp i j 表示從前i行種植,最後一...
狀態壓縮DP
總結狀壓dp轉移的方法 若某個狀態下可以對下 1.按二進位制讀入資料 2.列舉所有方案,如果合理 一行中沒有兩兩相鄰的 就儲存 i i 1 3.因為每一層的狀態只受上一層影響,因此迴圈兩次所有合理方案,為每乙個方案找到一系列下一層合理方案 4.遍歷每一行,並遍歷每一行的所有合理方案,若與預處理不矛盾...