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\n");

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\n",f[h&1][z1]);

53     }

54 }
View Code

 

          

 

你可能感兴趣的:(poj)