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; }