NEFU 155 超弦(插头DP)

超弦

Time Limit 5000ms

Memory Limit 65536K

description

前阵子hh看了一系列科普片<<优雅的宇宙>>,惊讶的发现整个世界都是由弦发出不同的震动所构成的.正如优雅小提琴由几根弦就能谱出无数华美的乐章一般优雅.
弦可以十分好的解释波粒二相形,测不准原理以及真空量子涨落,同时弦又可以描述为类似橡皮筋一般的拉伸,来符合弯曲时空的相对论理论.将爱因斯坦晚年一直致力的用一组方程描述世上万力的宏愿完成了,并且将现世两大基础物理学量子力学和相对论的冲突做了完美的解释.
但是弦理论至今只停留在理论(数学计算)阶段,没办法实际的实验,因为弦是一种比夸克还小几倍的宇宙基本元素(或者说根本没有体积),为了探究宇宙的奥秘,今天我们就随hh一起根据探索弦的形态.
我们已知的条件有:
1.在n*m的二维空间中存在k条弦.弦在这二维空间内不可自交.
2.弦有两种,开弦和闭弦,开弦就是一条线,闭弦是两端相连的环.
3.我们将n*m的空间分成n*m格,每格占一单位面积.
4.如果在一些格子上检测到放射性标记,那么该格就不可能存在弦.
5.其他格子必然被一条且仅被一条弦占有.
6.一条弦至少占两格.
现在,让我们根据这几条信息来推测k条超弦在这二维空间内的分布情况.

input

数据的第一行是一个数T(0 < T <= 100),表示接下去有T组测试数据.
每组测试数据第一行是三个整数n,m,k( 0 < n <= 10,0 < m <= 7,0 <= k < =5).
接下来n行,每行m个字符表示二维空间内放射性标记
'.'表示该格没有放射性标记
'X'表示该格带有放射性标记
(不包含其他字符)

output

每组测试数据输出一个整数表示k条弦在这二维空间的分布方案数(mod 10007).

sample_input

1
2 2 1
..
.X
2 3 2
...
...

sample_output

1
17

hint

 

source

NotOnlySuccess
题目:http://acm.nefu.edu.cn/JudgeOnline/problem/155.jsp

分析:这题算是插头DP的简单路径问题,直接套模板,真是郁闷,校赛时解不出来啊(因为还没学),这回一学完赶紧刷

题,居然wa了5次。。。。悲剧,实在不知道哪错了,要来标程,各种调试,发现我的程序K==0要特判,囧~~~果然

写程序慢的缺点不是来不及,而是忘记一些细节,本来有考虑的说。。。。

代码(还没优化work 函数,东北赛了先放着吧):

#include<cstdio> #include<cstring> using namespace std; const int mm=10007; int i,j,g1,g2,k,n,m,en,em,L,a,b,a1,a2,b1,b2,ans,t; inline void add(int& a,int b) { a+=b; if(a>=mm)a%=mm; } struct data { int s[mm],h[mm],p[mm],t,d[mm][6]; int hash(int x,int*dd,int w) { int i,j,c=x%mm; for(i=h[c];i>=0;i=p[i]) if(s[i]==x) { for(j=w;j<L;++j)add(d[i][j],*dd++); return i; } s[t]=x,p[t]=h[c],h[c]=t; for(d[t][0]=0,j=w;j<L;++j)d[t][j]=*dd++; return t++; } void clear() { t=0,memset(h,-1,sizeof(h)); } }f[2]; bool g[13][13]; int eat(int s,int a,int b,int c,bool f,bool l) { int n=1,x; while(n) { if(f)a<<=2,b<<=2,c<<=2; else a>>=2,b>>=2,c>>=2; x=s&c; if(x==a)++n; if(x==b)--n; } if(l)return (s^b)|a;else return s|c; } void work(int S,int*d) { int x,y; x=a&S,y=b&S; if(x==0&&y==0) { if(g[i+1][j]&&g[i][j+1])f[g2].hash(S|a1|b2,d,0); if(g[i+1][j])f[g2].hash(S|a,d,0); if(g[i][j+1])f[g2].hash(S|b,d,0); } else if(x==0&&y==b) { if(g[i][j+1])f[g2].hash(S,d,0); if(g[i+1][j])f[g2].hash((S^b)|a,d,0); f[g2].hash(S^b,d,1); } else if(x==a&&y==0) { if(g[i+1][j])f[g2].hash(S,d,0); if(g[i][j+1])f[g2].hash((S^a)|b,d,0); f[g2].hash(S^a,d,1); } else if(x==0&&y==b1) { if(g[i][j+1])f[g2].hash(S,d,0); if(g[i+1][j])f[g2].hash((S^b1)|a1,d,0); f[g2].hash(eat(S^b1,b1,b2,b,1,0),d,0); } else if(x==a1&&y==0) { if(g[i+1][j])f[g2].hash(S,d,0); if(g[i][j+1])f[g2].hash((S^a1)|b1,d,0); f[g2].hash(eat(S^a1,a1,a2,a,1,0),d,0); } else if(x==0&&y==b2) { if(g[i][j+1])f[g2].hash(S,d,0); if(g[i+1][j])f[g2].hash((S^b2)|a2,d,0); f[g2].hash(eat(S^b2,b2,b1,b,0,0),d,0); } else if(x==a2&&y==0) { if(g[i+1][j])f[g2].hash(S,d,0); if(g[i][j+1])f[g2].hash((S^a2)|b2,d,0); f[g2].hash(eat(S^a2,a2,a1,a,0,0),d,0); } else if(x==a1&&y==b)f[g2].hash(eat(S^a1^b,a1,a2,a,1,0),d,0); else if(x==a2&&y==b)f[g2].hash(eat(S^a2^b,a2,a1,a,0,0),d,0); else if(x==a&&y==b1)f[g2].hash(eat(S^a^b1,b1,b2,b,1,0),d,0); else if(x==a&&y==b2)f[g2].hash(eat(S^a^b2,b2,b1,b,0,0),d,0); else if(x==a1&&y==b1)f[g2].hash(eat(S^a1^b1,b1,b2,b,1,1),d,0); else if(x==a2&&y==b2)f[g2].hash(eat(S^a2^b2,a2,a1,a,0,1),d,0); else if(x==a2&&y==b1)f[g2].hash(S^a2^b1,d,0); else if(x==a&&y==b)f[g2].hash(S^a^b,d,1); else if(x==a1&&y==b2)f[g2].hash(S^a1^b2,d,1); } inline void end() { for(en=n-1;en>=0;--en) for(em=m-1;em>=0;--em) if(g[en][em])return; } int DP() { end(); if(L<=0)return en>=0?0:1; f[0].clear(); int v[6]={0}; v[0]=1; f[0].hash(0,v,0); for(g1=1,g2=i=ans=0;i<=n;++i) { for(k=0;k<f[g2].t;++k)f[g2].s[k]<<=2; a=3,b=3<<2,a1=1,a2=2,b1=1<<2,b2=2<<2; for(j=0;j<=m;a<<=2,b<<=2,a1<<=2,a2<<=2,b1<<=2,b2<<=2,++j) if(g[i][j])for(g1=!g1,g2=!g2,f[g2].clear(),k=0;k<f[g1].t;++k) { if(i==en&&j==em) { if(f[g1].s[k]==(a1|b2)||f[g1].s[k]==b||f[g1].s[k]==a||f[g1].s[k]==(a|b))add(ans,f[g1].d[k][L-1]);else continue; } work(f[g1].s[k],f[g1].d[k]); } } return ans; } int main() { // freopen("a.in","r",stdin); // freopen("aa.out","w",stdout); char c; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&L); 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("%d/n",DP()); } return 0; }

你可能感兴趣的:(NEFU 155 超弦(插头DP))