【hdu4285】 circuits
http://acm.hdu.edu.cn/showproblem.php?pid=4285 (题目链接)
题意
求不不能嵌套的回路个数为K的路径方案数。
Solution
插头dp,时限卡得太紧了,写的我蛋都要碎了T_T。
插头记录连通情况,对于嵌套,我们在合并连通块的时候,判断一下两侧的插头个数的奇偶。如果是奇数,那么合并后一定会出现嵌套;如果是偶数,那么合并后可能会出现嵌套。
细节
卡常经验传授:换行不用for一遍;hash不要开小了
代码
// hdu4285 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define LL long long #define HAS 300007 #define MOD 1000000007 #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; const int maxh=300010,maxs=1000010,maxd=15; int a[maxd][maxd],code[maxd],cnts[maxd],n,m,K; int size[2],tot[2][maxs],num; int nxt[maxs],head[maxh]; LL s[2][maxs]; char ch[maxd]; void decode(LL st) { num=st&63,st>>=6; for (int i=m;i>=0;i--) code[i]=st&7,st>>=3; } LL encode(int op,int m) { int cnt=0;LL st=0; if (op) { memset(cnts,-1,sizeof(cnts));cnts[0]=0; for (int i=0;i<=m;i++) { if (cnts[code[i]]==-1) cnts[code[i]]=++cnt; code[i]=cnts[code[i]]; } } for (int i=0;i<=m;i++) st=st<<3|code[i]; return st<<6|num; } void add(LL tmp,int p,int num) { int id=tmp%HAS; for (int i=head[id];i;i=nxt[i]) if (s[p][i]==tmp) {(tot[p][i]+=num)%=MOD;return;} s[p][++size[p]]=tmp;tot[p][size[p]]=num; nxt[size[p]]=head[id];head[id]=size[p]; } void shift() { for (int i=m;i;i--) code[i]=code[i-1];code[0]=0; } int main() { int T;scanf("%d",&T); while (T--) { memset(a,0,sizeof(a)); scanf("%d%d%d",&n,&m,&K); for (int i=1;i<=n;i++) { scanf("%s",ch+1); for (int j=1;j<=m;j++) a[i][j]=ch[j]=='.'; } int p=0; size[p]=1;tot[p][1]=1;s[p][1]=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { size[p^=1]=0; memset(head,0,sizeof(head)); for (int k=1;k<=size[p^1];k++) { decode(s[p^1][k]); int left=code[j-1],up=code[j]; if (!a[i][j]) { code[j-1]=code[j]=0; //if (j==m) shift(); add(encode(0,j==m ? m-1 : m),p,tot[p^1][k]); continue; } if (left && up) { if (left==up) { if (num>=K) continue; int tmp=0; for (int l=j+1;l<=m;l++) if (code[l]) tmp++; if (tmp&1) continue; num++;code[j-1]=code[j]=0; //if (j==m) shift(); add(encode(0,j==m ? m-1 : m),p,tot[p^1][k]); } else { for (int l=0;l<=m;l++) if (code[l]==left) code[l]=up; code[j-1]=code[j]=0; //if (j==m) shift(); add(encode(1,j==m ? m-1 : m),p,tot[p^1][k]); } } else if (left || up) { int tmp=left ? left : up; if (a[i][j+1]) { code[j-1]=0,code[j]=tmp; add(encode(0,j==m ? m-1 : m),p,tot[p^1][k]); } if (a[i+1][j]) { code[j-1]=tmp,code[j]=0; //if (j==m) shift(); add(encode(0,j==m ? m-1 : m),p,tot[p^1][k]); } } else { if (a[i][j+1] && a[i+1][j]) { code[j-1]=code[j]=13; add(encode(1,j==m ? m-1 : m),p,tot[p^1][k]); } } } } int ans=0; for (int i=1;i<=size[p];i++) if ((s[p][i]&63)==K) (ans+=tot[p][i])%=MOD; printf("%d\n",ans); } return 0; }
This passage is made by MashiroSky.