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
Source
2012 ACM/ICPC Asia Regional Tianjin Online
Recommend
liuyiding
题目: http://acm.hdu.edu.cn/showproblem.php?pid=4285
题意:给你一个方阵,有些地方能通过,有些地方不行,要求在方阵中方一些回路,覆盖所有可以通过的格子,这些回路不能相互包含。。。
分析:这题是插头DP的多条回路问题,不过这题的难点在于回路不能相互包含,这个问题我想了好久,没想到好的方法,想到增加插头数量。。。变得太复杂了
网上都说如果当前可以合并,必须满足包含这个回路的括号数为偶数,这个容易理解,如果是奇数的话,无论怎么做都不能使得回路不被包含。。。
还有这题有人说会爆内存要用map。。。我用了就爆内存了,没用就过了= =
而且速度还是比较快的,刷到前10了^_^
代码:
#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 Link(int s,int flag)
{
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);
else f[g2].push(Link(s^(x<<w),x==5),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;
}