acwing 291 蒙德里安的夢想(狀壓DP)

2021-10-22 16:35:05 字數 1405 閱讀 9436

我們發現,只要確定了橫向小方格的位置(藍色),其餘位置都是縱向的小方格,就已經確定了一種方案,所以我們只需要列舉合法的橫向小方格,那麼就相當於列舉了方案數。

先給出 f[i] [j] 的定義 :第 i 列的 j 狀態下的方案總數。j用二進位制表示,如圖,第二列現在的狀態(藍色)就是 100 (1表示此列有方格,0表示此列無方格)。

那麼我們可以按列向後更新,對於第三列,我們假設其狀態等於k(二進位制)滿足的要求如下: k的狀態不能與j有衝突,j狀態下有方格,那麼k狀態就不能有,就是像圖中紫色部分,也就是 k & j == 0 ;k狀態放完之後不能給第二列留下奇數行,就是像圖中粉色部分,如果放在粉色的位置上,因為我們其餘地方都是放縱向的小方格,如果留下的是奇數,那麼就不可能用縱向的填充滿 ,所以要保證 k | j 這個狀態下不能有奇數個空行

那麼最後的結果是什麼呢,就是第m列下,狀態是0的情況下,因為只有狀態是0,我們m+1列才不會有方格,才是合法的

#include

#include

#include

#include

#include

using

namespace std;

typedef

long

long ll;

const

int n =

12, m =

1<<12;

int n, m;

ll f[n]

[m];

//表示第i列j狀態下的方案數

bool st[m]

;//不能有奇數個0

intmain()

}else

}//最後一段

if(cnt &

1) st[i]

=false;}

memset

(f,0

,sizeof f)

; f[0]

[0]=

1;for(

int i =

1; i <= m; i++)}

}}cout << f[m][0

]<< endl;

}return0;

}

AcWing 291 蒙德里安的夢想

題意 給出 n 11,m 11 的矩陣,要求將矩陣全部恰好分成 1 times 2 或者 2 times 1 的小矩陣,問方案數。題解 主要是dp陣列的含義定義要了解,設 dp 表示的是第 i 行 j 形狀的方案數,這裡的 j 代表的是二進位制的狀態。想象乙個 01 串,然後在串中第 x 個0代表的...

Acwing 291 蒙德里安的夢想

求把 n m 的棋盤分割成若干個 1 2 的的長方形,有多少種方案。1 n,m 11 用f i s 表示第i行狀態為s的方案數 對於s 0表示i 1列無伸向第i列的方格,1表示有伸向第i列的方格 先預處理可用狀態 對這一題所有狀態都可用 state.clear for int i 0 i 1 找可轉...

291 蒙德里安的夢想

求把 n m 的棋盤分割成若干個 1 2 的的長方形,有多少種方案。例如當 n 2,m 4 時,共有 5 種方案。當 n 2,m 3 時,共有 3 種方案。如下圖所示 輸入包含多組測試用例。每組測試用例佔一行,包含兩個整數 n 和 m 當輸入用例 n 0,m 0 時,表示輸入終止,且該用例無需處理。...