pku 2411 Mondriaan's Dream 状态压缩DP

pku 2411 Mondriaan's Dream 状态压缩DP

简要题意:
给出一个n*m的矩形,要求用1*2的矩形拼出来(可以旋转),问总共有多少种拼法。

题解:
将第i行进行状态压缩表示
(0,0,0,0..0) 0代表向下没有插头,1代表向下有插头
然后向下一行转移方法就是
如果当前列有插头,则取消掉插头;
如果当前列没有插头:
1、如果下一列也没有插头,可以水平放一个小矩形或者竖直放两个小矩形,插头状态不变
2、如果下一列有插头,则竖直放一个小矩形,添加两个向下的插头
注意要用 long long
代码:
 1  # include  < iostream >
 2  # include  < cstring >
 3  # define getbit(c,pos) (((c) & ( 1 << (pos))) > 0 )
 4  using   namespace  std;
 5  void  add( int  code, int  now, int  m, long   long  dp[], int  num)
 6  {
 7      if (now == m)
 8        dp[code] += num;
 9      else
10     {
11          switch (getbit(code,now))
12         {
13             case   1 :
14                 add(code - ( 1 << now),now + 1 ,m,dp,num);
15                  break ;
16             case   0 :
17                  if (now != m - 1 &&! getbit(code,now + 1 ))
18                       add(code,now + 2 ,m,dp,num);
19                 add(code + ( 1 << now),now + 1 ,m,dp,num);
20                  break ;
21         };
22     }
23  }
24  int  main()
25  {
26       int  n,m;
27       while ( true )
28      {
29         cin >> n >> m;
30          if ( ! n &&! m)  break ;
31          long   long  dp[ 15 ][ 2048 ];
32         memset(dp, 0 , sizeof (dp));
33         dp[ 0 ][ 0 ] = 1 ;
34          for ( int  i = 0 ;i < n;i ++ )
35             for ( int  j = 0 ;j < ( 1 << m);j ++ )
36               if (dp[i][j])
37                   add(j, 0 ,m,dp[i + 1 ],dp[i][j]);
38         cout << dp[n][ 0 ] << endl;
39      }
40       return   0 ;
41  }
42 



你可能感兴趣的:(pku 2411 Mondriaan's Dream 状态压缩DP)