POJ2411 狀態壓縮DP(矩陣填塊)

2021-09-27 02:40:24 字數 1540 閱讀 6568

題目:

給你nm(1<=n,m<=11)的方格矩陣,要求用12的多公尺諾骨牌去填充,問有多少種填充方法。

分析:

首先我們定義如下這種填充表示方式:如果乙個骨牌是橫著放的,那麼它所在的兩個方格都填充1.如果它是豎著放的,那麼它所在的兩個格仔中,上面的那個填0,下面的這個填1.如下圖所示:

該矩陣的骨牌擺放方法和該矩陣的二進位制表示法是一一對應的。對於任意連續的兩行i-1和i行來說,第i-1行的二進位制表示和i行的二進位制表示有乙個相容的關係。

用pre表示前一行的二進位制形式,now表示後一行的二進位制形式,c表示當前操作的列號。c,pre,now初值都為0.由於是

從左邊位模擬到最右邊的位,所以對應3種操作的結果為:

上面的過程就是模擬出所有的相鄰兩行可以以什麼樣的(相互相容的)樣式放在兩行中

//path[i][0]---表示第i種兩行相互相容的方式中前一行值是多少(11111111這種形式轉化為了十進位制了)

//path[i][1]--表示第i中兩行相互相容的方式中當前行的二進位制形式對應的值是多少,

void get(int c,int pre,int now)//c表示當前列號,得到具有m列的矩陣的所有對應相容方式存入path中

get(c+1,(pre<<1)|1,now<<1); //豎著放

get(c+1,(pre<<1),(now<<1)|1); //不放

get(c+2,(pre<<2)|3,(now<<2)|3); //橫著放,

}

d[i][num]----表示第i行對應二進位制形式值為num時,有多少種方法,

然後就是遍歷,

d[0][(1總的**:

#include#include#includeusing namespace std;

int n,m,w;

const int maxn =15;

long long d[maxn][1<<15];

int path[5000000][2];//path[10][0]表示第11種(從0計數)相容方式的前一行二進位制形式對應的的值

//path[10][1]表示第11種(從0計數)相容方式的後一行二進位制形式對應的的值

//一共可能有(1<<11)*(1<<11)種相容方式

void get(int c,int pre,int now)//得到具有m列的矩陣的所有對應相容方式存入path中

get(c+1,(pre<<1)|1,now<<1);

get(c+1,(pre<<1),(now<<1)|1);

get(c+2,(pre<<2)|3,(now<<2)|3);

} int main()

printf("%i64d\n",d[n][(1<

}return 0;

}

poj 2411 狀態壓縮DP

用乙個vector容器來記錄當前狀態下有哪些狀態可以繼承。比如說vec i 裡面的所有的數代表當第一行為i狀態時,第二行的可行狀態。對於狀態i,其二進位制中0的地方表示為當前狀態為豎著的木板的下半部分。其二進位制中1的地方表示為當前狀態為橫著的木板或者豎著的木板的上半部分。include inclu...

POJ 2411 狀態壓縮DP

題目大意 給乙個h w的方格,現給出1 2和2 1的兩種小方塊,求出把h w方格鋪滿的不同方案數 1 h,w 11 分析 首先能想到的是如果h w為奇數,那麼肯定不能放滿,結果為0 如何表示狀態 從題目看資料很小,那麼很容易想到用二進位制來表示狀態,0表示當前方格沒放,1表示放了 這裡用dp r c...

poj2411 狀態壓縮dp

一道經典狀態壓縮dp題目。題意很明確,讓用1 2或2 1的小方格鋪滿地板。根據狀態壓縮的慣用思路,當前行的地板狀態是由當前行和上一行共同決定的,肯定要用乙個二進位制數表示一行的狀態,然後再用狀態轉移方程轉移求解。這道題可以這麼想,對於每個狀態,如果是1 2的橫著放,將兩個位置都標記為1,如果是2 1...