简单的状态压缩dp

题意: 给出一个n*m的矩形,(n和m都不大于11),现在想往这个举行里边放1*2的小矩形,问有多少中方法。

 

思路: 由于n的m都不大,因此我们可以想到用压缩dp的方法解决, 一行一行的处理, 每一行有很多状态,这一行的状态用上一行的状态转化过来。 dp[i][j]表示在第i行,状态时j时的情况数,这里的状态就是如果当前行这个位置放了东西那么这个位置就用1来表示,否则就用0来表示。 上一层的0,必须要用2*1的方法来填补,这样才不会重复计数, 也不会少计数,因为如果用1*2的矩形,可以看成是另外一个状态。

如果上一层的j能够转化成这一层的k ,那么dp[i][k] += dp[i-1][j];

AC 代码:

View Code
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 12;

LL dp[N][1<<N];
int n, m;

void solve()
 {
     if(n*m % 2)
      {
          printf("0\n");
          return;
      }
     int s, y = (1<<m)-1;
     memset(dp,0,sizeof(dp));
     dp[0][y] = 1;
     bool flag;
     for(int i=1; i<=n; i++)
      {
          for(int j=0; j<=y; j++)
           {
               for(int k=0; k<=y; k++)
                {


                    if((j|k) == y)
                     {
                         flag = 1;
                         s = k;
                         for(int w=0; w<m;w++)
                          {
                              if(!((1<<w)&j) )
                               s ^= (1<<w);
                          }
                         for(int w=0; w<m; w++)
                          {
                              if(s&(1<<w))
                               {
                                   if(s&(1<<(w+1)) )
                                    {
                                        w++;
                                    }
                                   else flag=0;
                               }
                          }

                          if(flag)
                           {
                               dp[i][k] += dp[i-1][j];
                           }
                     }
                }
           }
      }
    printf("%I64d\n",dp[n][y]);
 }

int main()
 {
     while(scanf("%d%d", &n, &m) != EOF)
      {
          if(n == 0 && m == 0)
           break;
          solve();
      }
     return 0;
 }

 

 

posted @ 2012-09-25 07:46  Gu Feiyang  阅读(206)  评论(0)    收藏  举报