poj2411

题意:题意:给定一个长宽小于等于11的矩形,问用1×2的小矩形填满,有多少种方法。

思路:经典的状态压缩题目

       用2进制表示状态

        f[i][opt]表是第i行状态为opt时的方法数

        f[i][opt] = sigma(f[i-1][opt1])期中opt1如果当前位上没放,那么opt就必须放一个竖的。。。

     答案为sigma(f[n][i]) 

 1 /*
 2   STATE:ACCEPTED
 3   TIME:2013.3.3
 4 */
 5 #include <iostream>
 6 #include <cstring>
 7 #include <string>
 8 #include <cstdlib>
 9 #include <cstdio>
10 #include <cmath>
11 #include <algorithm>
12 #include <vector>
13 const int maxm = 12;
14 long  long f[15][1 << maxm] , num;
15 int n , m ,  maxnum , ans ;
16 
17 void swap(int &a , int &b){  
18        int c = a;  
19            a = b; 
20            b = c;
21 }
22 
23 void updata(int i , int opt, int pos ){
24      if (pos == m){
25               f[i][opt] += num;
26               return;
27      }
28      updata(i , opt , pos + 1);
29      if (pos < m && !(1 << pos - 1 & opt) && !(1 << pos & opt) ) 
30            updata( i , opt | (1 << pos - 1) | (1 << pos) , pos + 1);
31 }
32 
33 void dp(){
34      memset(f , 0 , sizeof(f));
35      num = 1;
36      maxnum = (1 << m) - 1;
37      updata(1 , 0 , 1);
38      for (int i = 2; i <= n; ++i)
39          for (int opt = 0; opt < 1 << m; ++opt){
40                  if (f[i - 1][opt]) num = f[i - 1][opt];
41                  else continue;
42                  updata(i , ~ opt & maxnum , 1 );
43          }
44      printf("%lld\n",f[n][maxnum]);
45 }
46 
47 int main(){
48      freopen("poj2411.in","r",stdin);
49      freopen("poj2411.out","w",stdout);
50      scanf("%d%d",&n , &m);
51      while (n && m){
52         if (n < m) swap(n , m);
53         dp();
54         scanf("%d%d",&n ,&m);
55      }
56 }

 

   

posted on 2013-03-23 20:45  yzcstc  阅读(304)  评论(0编辑  收藏  举报