POJ 2411 狀態壓縮DP

2021-06-21 11:24:31 字數 1612 閱讀 5786

題目大意:給乙個h*w的方格,現給出1*2和2*1的兩種小方塊,求出把h*w方格鋪滿的不同方案數(1<=h,w<=11)

分析:首先能想到的是如果h*w為奇數,那麼肯定不能放滿,結果為0

如何表示狀態:從題目看資料很小,那麼很容易想到用二進位制來表示狀態,0表示當前方格沒放,1表示放了

這裡用dp[ r ][ cur ]表示前 r-1 行放滿,第 r 行狀態為 cur 時的方案數,同理,dp[ r-1 ][ lst ]表示前 r-2 行放滿,

第 r-1 行狀態為 lst 時的方案數; 狀態 lst 是由 cur 狀態推出來的( [1] 為什麼?),

所以dp[ r ][ cur ] = dp[ r ][ cur ] +dp[ r-1 ][ lst ]; 那麼dp[ h ][ (1<

[1] 先表示一下狀態,我們在考慮第 r 行,只考慮前 r 行,一共有 3 種狀態(cur表示第 r 行,lst表示第 r-1 行):

1、豎直放    cur<<1 | 1 ,   lst<<1 

2、橫著放    cur<<2 | 3,    lst<<2 | 3

3、不放        cur<<1,         lst<<1 | 1

先解釋一下:假設 cur = lst = 0,   假如豎直放,那麼 cur = 1, lst = 0, 意思是第 r 行第1列放,第 r-1 行第1列

不放(因為第 r 行要堅直放,所以第 r-1 行第 1 列不能放),直到放完最後一列,出現了兩個狀態 cur 和 lst,

其中 lst 不就是由 cur 狀態推出來的麼?並且保證第 r-1 行是滿的!

其中第一行只有兩種狀態,因為第一行上邊沒有,所以不能豎直放……

舉個例子:h = 3, w = 2;      dp[ r ][ cur ] += dp[ r-1 ][ lst ];

仔細看一看應該就可以看的懂了!下面是**:

#include#include#include#include#include#include#include#includeusing namespace std;

int h, w;

long long dp[12][2100];

void dfs(int r, int c, int cur, int lst)

if(c + 1 <= w) dfs(r, c+1, cur<<1, lst);

if(c + 2 <= w) dfs(r, c+2, cur<<2|3, lst);

}else

if(c + 1 <= w)

if(c + 2 <= w)

}}int main()

if(h < w) swap(h, w);

memset(dp, 0, sizeof(dp));

for(int r = 1; r <= h; ++r)

dfs(r, 0, 0, 0);

printf("%lld\n", dp[h][(1<

如有錯誤歡迎指正。

poj 2411 狀態壓縮DP

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

poj2411 狀態壓縮dp

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

poj 2411 狀態壓縮dp

題意 乙個n m的矩形用 1 2 的卡牌填滿 問共有多少種方法 方法 狀態壓縮 動規的思想 dp i j 表示前i 1行全部填滿 第i行狀態為j的方法總和 狀態j的二進位制狀態 0 表示該位被占用了 1 代表 該為是空的 狀態轉移方程 dp i j sum dp i 1 k 狀態j可由狀態k推出 起...