ZOJ 2563 Long Dominoes(状态压缩+dp)

题意:给定一个n*m的方格,问你用3*1的格子覆盖掉这个方格有多少种方法。。

解题思路:主要是状态压缩+dp,状态压缩和dp很神,http://www.cppblog.com/Ayue/archive/2011/12/04/161446.aspx

解题代码:

 1 // Author: darkdream
 2 // Created Time: 2013年09月06日 星期五 20时03分39秒
 3 
 4 #include<stdio.h>
 5 #include<string.h>
 6 #include<stdlib.h>
 7 #include<time.h>
 8 #include<math.h>
 9 #define LL long long
10 //freopen("/home/plac/problem/input.txt","r",stdin);
11 //freopen("/home/plac/problem/output.txt","w",stdout);
12 LL pp[10] , num[10],zt,row,n,m,dp[34][100000];
13 
14 void dfs(LL pos, LL status)
15 {
16   if(pos == n)
17   {
18     dp[row+1][status] += dp[row][zt];
19     return;
20   }
21   if(num[pos] == 0 )
22   {
23      if(pos + 2 < n  && num[pos+2] == 0  && num[pos+1] == 0 ) dfs(pos+3,status);
24      dfs(pos+1,status+ 2*pp[pos]);
25   }
26   else if(num[pos] == 1)
27      dfs(pos+1,status);
28   else {
29      dfs(pos+1,status+pp[pos]);
30   }
31 }
32 void change()
33 {
34   LL now = zt ,k = -1;
35   memset(num,0,sizeof(num));
36   while(now)
37   {
38     num[++k] = now%3; 
39     now = now/3;
40   }
41 
42 }
43 int main(){
44    pp[0] = 1;
45    for(int i = 1;i<= 9;i ++) pp[i] = pp[i-1]*3;
46 
47    while(scanf("%lld %lld",&n,&m) && (m||n))
48    {
49      if((m*n)%3 != 0  )
50      {
51        printf("0
");
52        continue;
53      }
54      memset(dp,0,sizeof(dp));
55      dp[0][0] = 1; 
56      LL nmax = pp[n];
57      for(row = 0 ; row < m ; row ++)
58        for(zt = 0 ; zt < nmax; zt ++)
59        if(dp[row][zt])
60        {
61          change();
62          dfs(0,0);
63        }
64      printf("%lld
",dp[m][0]);
65    }
66 return 0 ;
67 }
View Code
没有梦想,何谈远方
原文地址:https://www.cnblogs.com/zyue/p/3306132.html