zoukankan      html  css  js  c++  java
  • 【BZOJ1814】Ural 1519 Formula 1 插头DP

    【BZOJ1814】Ural 1519 Formula 1

    题意:一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数。(n,m<=12)

    题解:插头DP板子题,刷板子,附带题解链接

    如何存放状态呢?可以采用hash,我们的hash表形如一个队列,每次新加入一个状态时,就沿着这个状态在队列中对应的hash值不断向后找,直到找到这个状态或者发现一个空位为止。

    本题我的状态采用了4进制表示。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    const int limit=99991;
    int n,m,k,tot[2],nn,mm;
    bool v[20][20];
    char str[20];
    ll tag,ans;
    int hs[limit],state[2][limit];
    ll dp[2][limit];
    inline void upd(ll S)
    {
    	register int pos=S%limit;
    	while(hs[pos])
    	{
    		if(state[k][hs[pos]]==S)
    		{
    			dp[k][hs[pos]]+=tag;
    			return ;
    		}
    		pos++;
    		if(pos==limit)	pos=0;
    	}
    	hs[pos]=++tot[k],state[k][tot[k]]=S,dp[k][tot[k]]=tag;
    }
    int main()
    {
    	register int i,j,t,u,tmp,p,q,x,y,S,T;
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=n;i++)
    	{
    		scanf("%s",str+1);
    		for(j=1;j<=m;j++)asdasd
    		{
    			v[i][j]=str[j]=='.';
    			if(v[i][j])	nn=i,mm=j;
    		}
    	}
    	tot[0]=1,state[0][1]=0,dp[0][1]=1;
    	for(i=1;i<=n;i++)
    	{
    		for(j=1;j<=m;j++)
    		{
    			k^=1;
    			memset(hs,0,sizeof(hs));
    			memset(state[k],0,sizeof(state[k][0])*(tot[k]+1));
    			memset(dp[k],0,sizeof(dp[k][0])*(tot[k]+1));
    			tot[k]=0;
    			for(t=1;t<=tot[k^1];t++)
    			{
    				S=state[k^1][t],tag=dp[k^1][t],y=j<<1,x=y-2,p=(S>>x)&3,q=(S>>y)&3,T=S^(p<<x)^(q<<y);
    				if(!v[i][j])
    				{
    					if(!p&&!q)	upd(T);
    					continue;
    				}
    				if(p==0&&q==0&&v[i][j+1]&&v[i+1][j])
    				{
    					upd(T|(1<<x)|(2<<y));
    					continue;
    				}
    				if((p==0&&q==1)||(p==1&&q==0))
    				{
    					if(v[i+1][j])	upd(T|(1<<x));
    					if(v[i][j+1])	upd(T|(1<<y));
    					continue;
    				}
    				if((p==0&&q==2)||(p==2&&q==0))
    				{
    					if(v[i+1][j])	upd(T|(2<<x));
    					if(v[i][j+1])	upd(T|(2<<y));
    					continue;
    				}
    				if(p==2&&q==1)
    				{
    					upd(T);
    					continue;
    				}
    				if(p==1&&q==2&&i==nn&&j==mm)
    				{
    					ans+=tag;
    					continue;
    				}
    				if(p==1&&q==1)
    				{
    					for(tmp=0,u=y+2;u<=m+m&&tmp>=0;tmp+=((T>>u)&1)-((T>>(u+1))&1),u+=2);
    					u-=2,upd(T^(3<<u));
    					continue;
    				}
    				if(p==2&&q==2)
    				{
    					for(tmp=0,u=x-2;u>=0&&tmp>=0;tmp+=((T>>(u+1))&1)-((T>>u)&1),u-=2);
    					u+=2,upd(T^(3<<u));
    					continue;
    				}
    			}
    		}
    		for(t=1;t<=tot[k];t++)	state[k][t]<<=2;
    	}
    	printf("%lld",ans);
    	return 0;
    }
  • 相关阅读:
    生成排列与生成子集
    赛后总结AtCoder Beginner Contest 090(Beginner)
    树状数组笔记
    论怎么记住tarjan的板子
    tarjan缩点-受欢迎的牛-笔记
    tarjan模板(%%%hzwer)-2.0
    tarjan模板(%%%hzwer)
    匈牙利算法学习笔记
    最短路-Car的旅行路线
    数据结构 笔记1 搜索树
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8010738.html
Copyright © 2011-2022 走看看