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;
}
浙公网安备 33010602011771号