zoukankan      html  css  js  c++  java
  • 【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
    ",ans);
    	}
        return 0;
    }
    
  • 相关阅读:
    eclipse中字母大小写转换快捷键
    Java中删除文件、删除目录及目录下所有文件
    request.getRequestDispatcher()和response.sendRedirect()
    hibernate4 二级缓存demo实例
    Srping整合EhCache
    收集的几个好用的maven mirror
    Hibernate所用15个jar包
    DRUID连接池的使用
    no persistent classes found for query class: FROM com.vrv.paw.domain.User
    正向代理和反向代理
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6414349.html
Copyright © 2011-2022 走看看