题意:不经过为0的格子(1的格子都要经过),问能形成几个环。。
插头DP入门题。。。
用一个哈希表把状态和数量对应的存起来,然后根据轮廓线转移就好。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int MAXN=110000;
struct HASHMAP
{
ll sum[MAXN];
int S[MAXN];
int head[MAXN],size;
void init()
{
memset(head,-1,sizeof(head));
size=0;
}
void push(int SS,ll num)
{
int s=SS%MAXN;
while(head[s]!=-1&&S[head[s]]!=SS)
s=(s+1)%MAXN;
if(head[s]!=-1)
sum[head[s]]+=num;
else
{
sum[size]=num;
S[size]=SS;
head[s]=size++;
}
}
ll get(int SS)
{
int s=SS%MAXN;
while(head[s]!=-1&&S[head[s]]!=SS)
s=(s+1)%MAXN;
if(head[s]!=-1)
return sum[head[s]];
else
return 0;
}
}dp[2];
int pre,now;
int get(int S,int p,int l=1)
{
if(p<0)
return 0;
return (S>>p)&((1<<l)-1);
}
void set(int &S,int p,int v,int l=1)
{
S^=get(S,p,l)<<p;
S^=(v&((1<<l)-1))<<p;
}
int mp[12][12];
int main()
{
int t,n,m,i,j,k,flag=1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",&mp[i][j]);
}
}
now=1,pre=0;
dp[now].init();
dp[now].push(0,1);
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
swap(now,pre);
dp[now].init();
for(k=0;k<dp[pre].size;k++)
{
int S=dp[pre].S[k];
ll num=dp[pre].sum[k];
int p=get(S,j);
int q=get(S,j+1);
if(mp[i][j]==0)
{
if(p==0&&q==0)
dp[now].push(S,num);
continue;
}
if(p==0&&q==0)
{
if(mp[i+1][j]&&mp[i][j+1])
{
set(S,j,1);
set(S,j+1,1);
dp[now].push(S,num);
}
}
else if(p^q)
{
if(mp[i+p][j+q])
dp[now].push(S,num);
set(S,j,q);
set(S,j+1,p);
if(mp[i+q][j+p])
dp[now].push(S,num);
}
else if(p==1&&q==1)
{
set(S,j,0);
set(S,j+1,0);
dp[now].push(S,num);
}
}
}
for(j=0;j<dp[now].size;j++)
{
dp[now].S[j]<<=1;
}
}
ll ans=dp[now].get(0);
printf("Case %d: There are %I64d ways to eat the trees.\n",flag++,ans);
}
return 0;
}