# circuits

Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 381    Accepted Submission(s): 128

Problem Description
Given a map of N * M (2 <= N, M <= 12) , '.' means empty, '*' means walls. You need to build K circuits and no circuits could be nested in another. A circuit is a route connecting adjacent cells in a cell sequence, and also connect the first cell and the last cell. Each cell should be exactly in one circuit. How many ways do we have?

Input
The first line of input has an integer T, number of cases.
For each case:
The first line has three integers N M K, as described above.
Then the following N lines each has M characters, ‘.’ or ‘*’.

Output
For each case output one lines.
Each line is the answer % 1000000007 to the case.

Sample Input
2 4 4 1 **.. .... .... .... 4 4 1 .... .... .... ....

Sample Output
2 6

Source

Recommend
liuyiding

代码：
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int mm=100007;
const int mod=1000000007;
typedef long long LL;
struct hashTable
{
int h[mm],s[mm],p[mm],t;
LL v[mm][37];
void push(int w,int j,LL val)
{
int i,id=w%mm;
for(i=h[id];i>=0;i=p[i])
if(s[i]==w)
{
v[i][j]+=val;
if(v[i][j]>=mod)v[i][j]=v[i][j]%mod;
return;
}
v[t][j]=val,s[t]=w,p[t]=h[id],h[id]=t++;
}
void clear()
{
while(t--)memset(v[t],0,sizeof(v[t]));
t=0,memset(h,-1,sizeof(h));
}
}f[2];
int i,j,k,g1,g2,n,m,K,t;
bool g[22][22];
char c;
bool ok(int s)
{
if(s==1)return g[i+1][j];
if(s==2)return g[i][j+1];
return g[i+1][j]&&g[i][j+1];
}
bool can(int s)
{
int sum=0,r=j;
while(r--)
{
if((s&3)==1)++sum;
if((s&3)==2)--sum;
s>>=2;
}
return (sum&1)==0;
}
{
int w,n=1,x=3<<(j<<1),a=(2-flag)<<(j<<1);
while(n)
{
if(flag)x<<=2,a<<=2;
else x>>=2,a>>=2;
w=s&x;
if(w)n+=(w==a)?1:-1;
}
return s^x;
}
void Work(int s,int k,LL val)
{
int e,w=j<<1,x=(s>>w)&15;
if(x==9)
{
if(k<K&&can(s))f[g2].push(s^(9<<w),k+1,val);
}
else if(!x)
{
if(ok(3))f[g2].push(s^(9<<w),k,val);
}
else if(!(x&3)||!(x&12))
{
if(x&3)e=0,x|=x<<2;
else e=1,x|=x>>2;
if(ok(1+e))f[g2].push(s,k,val);
if(ok(1+!e))f[g2].push(s^(x<<w),k,val);
}
else if(x==6)f[g2].push(s^(x<<w),k,val);
}
LL PlugDP()
{
if(K>n*m/4)return 0;
f[0].clear();
f[0].push(0,0,1);
for(g2=i=0;i<n;++i)
{
for(k=0;k<f[g2].t;++k)f[g2].s[k]<<=2;
for(j=0;j<m;++j)
if(g[i][j])for(g1=g2,g2=!g2,f[g2].clear(),k=0;k<f[g1].t;++k)
for(int s=0;s<K;++s)
if(f[g1].v[k][s])Work(f[g1].s[k],s,f[g1].v[k][s]);
}
LL ret=0;
for(k=0;k<f[g2].t;++k)
if(!f[g2].s[k])ret+=f[g2].v[k][K];
return ret;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&K);
memset(g,0,sizeof(g));
for(i=0;i<n;++i)
for(j=0;j<m;++j)
scanf(" %c",&c),g[i][j]=(c=='.');
printf("%I64d\n",PlugDP());
}
return 0;
}


©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客