狀壓DP(奇怪的東西)

 簡介

 狀態壓縮動態規劃(簡稱狀壓DP)是很是典型的一類DP。他是利用二進制來描述狀態的一種DP方式,你們都知道,DP是解決多階段決策最優化問題的思想方法,可是有時候階段多了,維度多了,數組也就爆了,由於雖然維度多,可是有些空間可能用不到,這就很浪費了,(主要是維度多了處理麻煩很噁心)因此咱們就把咱們就把一組數據壓到一個int變量裏面(只要是整形,什麼都好啦)數組

  舉個生動形象的例子,在01揹包中,n個物品的選擇方式,就能夠用二進制數來表示:1 0 1 1 0(n=5),從低位開始,表示1不選,2選,3選,4不選,5選。優化

  既然它與二進制有關,因此咱們就須要講一講二進制啦spa

位運算

基本運算

名稱code

做用blog

舉例get

左移(<<) 位左移運算將整個數按位左移若干位,左移後空出的部分0。 5(101)<<2=20(10100) 
右移(>>) 位右移運算將整個數按位右移若干位,右移後空出的部分填0。 5(101)>>2=1(1) 
按位與(&) 會將兩個十進制數在二進制下進行與運算,而後返回其十進制下的值。在某一位上,只有兩個數都是1才返回1 5(101)&2(10)=0 
按位或(|) 會將兩個十進制數在二進制下進行或運算,而後返回其十進制下的值。在某一位上,只要有一個數是1就返回1 5(101)|2(10)=7(111) 
按位異或(^) 會將兩個十進制數在二進制下進行異或運算,而後返回其十進制下的值。在某一位上,只有兩個數相同才返回1 5(101)^2(10)=0 
按位非(~) 把0變成1,1變成0,而後返回其十進制下的值。 咳咳,最好不要輕易用,由於int有32位(二進制),前面的所有會變成1 

進階運算

 

檢查第i位是不是 1it

if(1<<(i-1)&x)...

檢查第i位是不是 0io

if(1<<(i-1)&x==0)...

統計x中有多少個 1table

while(x) { cnt += x&1; x >>= 1; }

檢查x中是否有相鄰的 1ast

if(x&(x<<1))...

計算x最低位1表明的值

int lowbit(int x) { return x&(-x); }

把第i位變成 1

x |= (1<<(i-1))

把第i位變成 0

x &= ~(1<<(i-1))

把第i位取反

x ^= (1<<(i-1)

末i位取反

x^(1<<(i-1))

x包含y

if(x&y==y)...    OR if(x|y==x)...

取右邊連續的1

(x^(x+1))>>1

把右邊連續的0變成1

x&(x-1)

把右邊連續的1變成0

x|(x+1)

把右邊第一個0變成1

x|(x+1)

例題 P1879 [USACO06NOV]玉米田Corn Fields

  這是一道典型的狀壓DP(廢話,學的狀壓不給狀壓給什麼)

  咱們用一個M數組來存儲每一行的狀況(土地是否貧瘠),而後用state數組表示某一種種植方法是否能夠知足任意兩個種植物不相鄰,(bool數組)。

  而後開始一行一行的枚舉狀態,若是可用而且沒有貧瘠土地,就枚舉上一排的,看不相鄰的狀況就轉移,最後把最後一行全部的狀況累計起來便可。

code

 

例題 P1896 [SCOI2005]互不侵犯

  仍是和玉米田差很少的操做,可是dp數組須要加一維,因此就成了在某一行的某種狀態中已經放了x個國王有幾種方法,剩下的就和上一個例題差很少了

code

相關文章
相關標籤/搜索