POJ2411

题目大意:一个宽w高为h的棋盘,现在要用1*2的多米诺骨牌不重叠地覆盖整个棋盘,问有多少种方案。

h<11,w<11

分析:1.h*w若为奇数,则无解。

        2.按行处理。处理第i行时,保证前i-1行全部覆盖,当前行的状态为state。

以f[i][state]表示处理到第i行,第i行的状态为state,且前i-1行全部填满的方案数。

            f[i][state]=∑f[i-1][state2]

 需要统计有哪些state2可以转移到state。这个可以用dfs来预处理出来。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 #include<cstring>
 6 using namespace std;
 7 #define MAXN 2200
 8  vector<int> arr[MAXN];
 9 long long f[2][MAXN],h,w,n,ss;
10 int tt;
11 void find(int s,int t,int i)
12 {
13     if(s==0||i>=n){arr[ss].push_back(t);return;}
14     if(s&1)
15     {
16         if(s&2)
17             find(s>>2,t,i+2);
18         find(s>>1,t^(1<<i),i+1);
19     }
20     else
21         find(s>>1,t,i+1);
22 }
23 int main()
24 {
25     n=11;
26     int z=(1<<n)-1;
27         for(int i=0;i<=z;i++)
28         {
29             ss=i;
30             find(i,z,0);
31         }
32      while(scanf("%d%d",&h,&w)&&(w||h))
33     {
34         memset(f,0,sizeof f);
35         if(w%2&&h%2)
36         {printf("0
");
37             continue;
38         }
39         int z1=(1<<w)-1;
40         f[0][z1]=1;
41         for(int i=1;i<=h;i++)
42         {
43             for(int j=0;j<=z1;j++)
44             {
45                 f[i&1][j]=0;
46                 for(int k=0;k<arr[j].size();k++)
47                 {
48                     f[i&1][j]+=f[!(i&1)][arr[j][k]&z1];
49                 }
50             }
51         }
52         printf("%I64d
",f[h&1][z1]);
53     }
54 }
View Code

          

原文地址:https://www.cnblogs.com/hefenghhhh/p/4609927.html