poj 2411

来源:互联网 发布:手机网络加速器官 编辑:程序博客网 时间:2024/05/17 22:27

       题目意思很好懂,就不说了,这题是典型的状态压缩dp。

       这题其实做不出,参考了UESTC一个神的代码。他的解题思路是:

       用2进制的01表示不放还是放
       第i行只和i-1行有关
       枚举i-1行的每个状态,推出由此状态能达到的i行状态
       如果i-1行的出发状态某处未放,必然要在i行放一个竖的方块,所以我对上一行状态按位取反之后的状态就是放置了竖方块的状态。
       然后用搜索扫一道在i行放横着的方块的所有可能,并且把这些状态累加上i-1的出发状态的方法数,如果该方法数为0,直接continue。
       举个例子
       2 4
       1111
       1111
       状态可以由
       1100 0000 0110 0011 1111
       0000 0000 0000 0000 0000
       这五种i-1的状态达到,故2 4 的答案为5

 

       以下是代码:

  1. #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    __int64 dp[30][1<<12],temp;
    int n,m;
  2. void dfs(int i,int s,int pos)
    {
     if(pos==m)
     {
      dp[i][s]+=temp;
      return ;
     }
     dfs(i,s,pos+1);
     if(pos<=m-2 && !(s&1<<pos) && !(s&1<<pos+1))
      dfs(i,s|1<<pos|1<<pos+1,pos+2);
    }
  3. int main()
    {
     while(scanf("%d%d",&n,&m)==2)
     {
      if(!n && !m)  break;
      memset(dp,0,sizeof(dp));
      temp=1;
      dfs(1,0,0);
      int i,j;
      for(i=2;i<=n;i++)
       for(j=0;j<1<<m;j++)
       {
        if(dp[i-1][j])
         temp=dp[i-1][j];
        else
         continue;
        dfs(i,~j&((1<<m)-1),0);
       }
      printf("%I64d/n",dp[n][(1<<m)-1]);
     }
     return 0;
    }