http://acm.hdu.edu.cn/showproblem.php?pid=1693
这题是之前只有一个哈密尔顿路径问题的弱化版,那么只需要2进制状态就行了,有线连过来或者无就行,而且可以全部跑完最后记录状态为0的树,不用在最后一个位置记录答案。
但是我在最后一个位置记录答案时wa了一发,加了一个判断最后这个位置除了j-1和j位是1其他全是0才过,但按道理我每次设为1都判断了下面和右边是不是0,应该不会出现问题啊。。。不是很懂,写了个对拍还没拍出来,建议拍到明早
upd:拍出来了,经典if后面加分号不报错然后出事了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=20;
const int hs=299997;
int n,m,cnt[2],now,tot,mt,cas;ll ans;
int a[maxl][maxl],mi[maxl];
int q[2][hs+3],hd[hs+3],nxt[hs+3],mark[hs+3];
ll dp[2][hs+3];
inline void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
a[i][m+1]=0;
for(int i=1;i<=m;i++)
a[n+1][i]=0;
}
inline void insert(int bit,ll val)
{
int u=bit%hs+1;
if(mark[u]!=mt)
hd[u]=0,mark[u]=mt;
for(int i=hd[u];i;i=nxt[i])
if(q[now][i]==bit)
{
dp[now][i]+=val;
return;
}
nxt[++cnt[now]]=hd[u];
hd[u]=cnt[now];
q[now][cnt[now]]=bit;
dp[now][cnt[now]]=val;
}
inline void mainwork()
{
ans=0;int bit,b1,b2;ll val;
cnt[now]=1;q[now][1]=0;dp[now][1]=1;
for(int i=1;i<=n;i++)
{
for(int k=1;k<=cnt[now];k++)
q[now][k]*=2;
for(int j=1;j<=m;j++)
{
mt++;now^=1;cnt[now]=0;
for(int k=1;k<=cnt[now^1];k++)
{
bit=q[now^1][k];val=dp[now^1][k];
b1=(bit>>(j-1))&1;b2=(bit>>j)&1;
if(!a[i][j])
{
if(b1==0 && b2==0)
insert(bit,val);
}
else
{
if(b1==0 && b2==0)
{
if(a[i+1][j] && a[i][j+1])
insert(bit^mi[j-1]^mi[j],val);
}
else if(b1==0 && b2==1)
{
if(a[i+1][j])
insert(bit^mi[j-1]^mi[j],val);
if(a[i][j+1])
insert(bit,val);
}else if(b1==1 && b2==0)
{
if(a[i+1][j])
insert(bit,val);
if(a[i][j+1])
insert(bit^mi[j-1]^mi[j],val);
}
else
insert(bit^mi[j-1]^mi[j],val);
}
}
}
}
ans=0;
for(int k=1;k<=cnt[now];k++)
if(q[now][k]==0)
ans+=dp[now][k];
}
inline void print()
{
printf("Case %d: There are %lld ways to eat the trees.\n",cas,ans);
}
int main()
{
mi[0]=1;
for(int i=1;i<=12;i++)
mi[i]=mi[i-1]<<1;
int t;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}