http://poj.org/problem?id=2411

完全自己做的话 还真不行 能力还是不够呀

横着的两个小格 和竖着的第一个小格用 0 表示 竖着的第二个小格用 1表示

逐行更新 更新时用 DFS 最后一行要注意特判一下

代码及其注释:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<stack>
#include<algorithm>
#define LL long long

using namespace std;

LL sum[15][1<<11];//你懂得
LL Num;
int n,m;
void Dfs(int x,int i,int k,int j)//x 是第几位 用到k的最后一位比较 需要不断更新 j记录所有为取完的和
{
    if(x==m+1)
    {
        Num+=sum[i-1][j];//累加
        return ;
    }
    if(k%2==1)
    {
        Dfs(x+1,i,k/2,j);//此位只能找 0 
    }else
    {
        Dfs(x+1,i,k/2,j+int(pow(2,x-1)));//此位找 1
        if(x!=m&&k/2%2!=1)
        {
            Dfs(x+2,i,k/2/2,j);//此位和下一位都找 0
        }
    }
}
bool Can(int k)//特判一下最后一行
{
    int num=0;
    for(int i=1;i<=m;++i)
    {
        if(k%2==1)
        {
            if(num%2==1)
            return false;
            else
            num=0;
        }else
        {
            ++num;
        }
        k=k/2;
    }
    if(num%2==1)
    return false;
    return true;
}
int main()
{
   while(scanf("%d %d",&n,&m)!=EOF)
   {
       if(n==0&&m==0)
       break;
       if(n%2&&m%2)
       {
           printf("0\n");
           continue;
       }
       if(n==1||m==1)
       {
           printf("1\n");
           continue;
       }
       memset(sum,0,sizeof(sum));
       sum[1][0]=1;
       int M=1<<m;
       LL ans=0;
       for(int i=2;i<=n;++i)
       {
           for(int j=0;j<M;++j)
           {
               if(i==n&&Can(j)==false)//最后一行
               continue;
               Num=0;
               Dfs(1,i,j,0);
               sum[i][j]+=Num;//累加
               if(i==n)
               ans+=sum[i][j];
           }
       }
       cout<<ans<<endl;
   }
   return 0;
}

  

 

posted on 2012-07-20 19:48  夜->  阅读(185)  评论(0编辑  收藏  举报