求把 \(n×m\) 的棋盤分割成若干個 \(1×2\) 的的長方形,有多少種方案。
例如當 \(n=2,m=4\) 時,共有 \(5\) 種方案。當 \(n=2,m=3\) 時,共有 \(3\) 種方案。
如下圖所示:
輸入包含多組測試用例。
每組測試用例佔一行,包含兩個整數 \(n\) 和 \(m\)。
當輸入用例 \(n=0,m=0\) 時,表示輸入終止,且該用例無需處理。
每個測試用例輸出乙個結果,每個結果佔一行。
資料範圍
\(1≤n,m≤11\)
輸入樣例:
1 2
1 31 4
2 22 3
2 42 11
4 11
0 0
輸出樣例:101
235144
51205
狀壓dp分析:總的合法方案數為橫著放小方塊的總的合法方案數,其餘由豎著的小方塊塞進去即可,設當前列 \(i\) 由前面開始橫著放的小方塊狀態為 \(1\),否則為 \(0\),則其可由 \(i-1\) 轉移過來,注意第一列和最後一列的下一列狀態為 \(0\)
// problem: 蒙德里安的夢想
// contest: acwing
// url:
// memory limit: 64 mb
// time limit: 5000 ms
// // powered by cp editor (
// %%%skyqwq
#include //#define int long long
#define help
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long ll;
typedef pairpii;
typedef pairpll;
template bool chkmax(t &x, t y)
template bool chkmin(t &x, t y)
template void inline read(t &x)
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}const int n=1<<11;
int n,m;
ll f[12][n];
bool st[n];
int main()
else
cnt++;
if(cnt&1)st[i]=false;
} memset(f,0,sizeof f);
f[0][0]=1;
for(int i=1;i<=m;i++)
for(int j=0;j<1<
for(int k=0;k<1<
if((j&k)==0&&st[j|k])f[i][j]+=f[i-1][k];
cout<
}return 0;
}
AW291 蒙德里安的夢想
題目位址 易錯點 結論1 在合法狀態下,對於每個橫塊的正上方兩個格仔中任意乙個格仔,一定屬於某個橫塊的一部分或某個豎塊的下半部.證明 假設有乙個橫塊的正上方兩格中的某格為乙個豎塊的上半部,由定義可知該情況不成立.對於任意乙個格仔,只有可能為以下三種狀態之一 豎塊上半部 豎塊下半部 半個橫塊.由 1 ...
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 找可轉...