1. 程式人生 > >[poj P2411] Mondriaan's Dream

[poj P2411] Mondriaan's Dream

source names 一個 fine include fas urn ngs poj

[poj P2411] Mondriaan‘s Dream

Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 18023 Accepted: 10327

Description

Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his ‘toilet series‘ (where he had to use his toilet paper to draw on, for all of his paper was filled with squares and rectangles), he dreamt of filling a large rectangle with small rectangles of width 2 and height 1 in varying ways.

技術分享

Expert as he was in this material, he saw at a glance that he‘ll need a computer to calculate the number of ways to fill the large rectangle whose dimensions were integer values, as well. Help him, so that his dream won‘t turn into a nightmare!

Input

The input contains several test cases. Each test case is made up of two integer numbers: the height h and the width w of the large rectangle. Input is terminated by h=w=0. Otherwise, 1<=h,w<=11.

Output

技術分享For each test case, output the number of different ways the given rectangle can be filled with small rectangles of size 2 times 1. Assume the given large rectangle is oriented, i.e. count symmetrical tilings multiple times.

Sample Input

1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11
0 0

Sample Output

1
0
1
2
3
5
144
51205

Source

Ulm Local 2000 哎,我好弱啊。。。 一個狀壓DP都想不到。。。 先列出總轉移方程:f[i][j]=sigma(ok(j,k))f[i-1][k]。 其中j,k是二進制狀態,i是第幾行。 那麽,我們無非就是考慮第i行和第i-1行的狀態是否兼容。 如何判斷是否兼容? 對於兩行k,k+1兩個狀態,第i位分別為u和d。 我們設狀態裏面“1”表示當前的格子已經被填了,且是被上一行填入;“0”表示未被填。 如果u==1且d==0,我們可以只能跳到下一列進行判斷;否則, 如果u==1且d==1,顯然這個狀態是不合法的;否則, 如果u==0且d==0,那麽上面那一行的下一列必定填入一個橫排(且當前為0,表示還沒有被填入),我們可以將它當做是被上一行填入的(即更改k行下一列的狀態,0->1);否則 如果u==0且d==1,顯然正好是當前列放一塊豎的。 code: 技術分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #define LL long long
 6 #define idx(x,i) ((x>>i)&1)
 7 using namespace std;
 8 const int lim=20;
 9 int n,m,S; LL f[lim][1<<lim];
10 vector <int> o[1<<lim];
11 bool jug(int su,int sd) {
12     for (int i=0; i<m; i++) {
13         int ku=idx(su,i),kd=idx(sd,i);
14         if (!kd&&ku) continue;
15         if (ku) return 0; else
16         if (!kd) {
17             if (i<m-1&&!idx(su,i+1)) su|=1<<(i+1); else return 0;
18         }
19     }
20     return 1;
21 }
22 int main() {
23     while (scanf("%d%d",&n,&m),n|m) {
24         S=1<<m;
25         for (int i=0; i<S; i++) o[i].clear();
26         for (int i=0; i<S; i++)
27             for (int j=0; j<S; j++) if (jug(i,j)) o[j].push_back(i);
28         memset(f,0,sizeof f),f[0][0]=1;
29         for (int i=1; i<=n; i++)
30             for (int j=0; j<S; j++)
31                 for (int k=0,s=o[j].size(); k<s; k++)
32                 f[i][j]+=f[i-1][o[j][k]];
33         printf("%lld\n",f[n][0]);
34     }
35     return 0;
36 }
View Code

[poj P2411] Mondriaan's Dream