90pts WAon#8
查看原帖
90pts WAon#8
788951
TLE_AK楼主2024/6/13 12:16
#include<bits/stdc++.h>
using namespace std;
#define int long long

namespace acac
{
	char A[30][30];
	int hlist[300010][4],nex[300010][4],dy[300010][4],sz[10],dp[300010][5],zt,pre=1; 
	//哈希表前2,滚动计算大小,dp数组,0/1状态 
	
	const int mod=299993;
	int ans;
	
	void ins(int now,int num)//hash表加入,因为此处时空不足,所以必须用hash表qwq 
	{
		int w=now%mod+1;
		for(int i=hlist[w][zt];i;i=nex[i][zt])
		{
			if(dy[i][zt]==now)
			{
				dp[i][zt]+=num;
				return ;
			}
		}
		
		dy[++sz[zt]][zt]=now;
		nex[sz[zt]][zt]=hlist[w][zt];
		hlist[w][zt]=sz[zt];
		dp[sz[zt]][zt]=num;
		return ;
	}

	//zt:前,pre:后,0:无,1:left,2:right ->1:(,2:)

	int main()
	{
		int n,m;
		scanf("%lld%lld",&n,&m);
		int edx=0,edy=0;//最后一个合法位置 
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				char ch=getchar();
				while(ch!='.'&&ch!='*')
				{
					ch=getchar(); 
				}
				A[i][j]=ch;
				if(ch=='.')edx=i,edy=j; 
			}
		}
		ins(0,1);
		//4进制表示 
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=sz[zt];j++)
			{
				dy[j][zt]<<=2;	
			}	
			//因为最后一位少一个->的插头,补上
			for(int j=1;j<=m;j++)
			{
				memset(hlist,0,sizeof(hlist));
				zt^=1,pre^=1;
				sz[zt]=0;
			//	cout<<zt<<' '<<pre<<' '<<sz[pre]<<endl;
				for(int k=1;k<=sz[pre];k++)
				{
					int now=dy[k][pre],val=dp[k][pre];
					//cout<<now<<endl;
					int ct1=(now>>(2*(j-1)))&3,ct2=(now>>(2*j))&3;
				//	cout<<ct1<<' '<<ct2<<' '<<i<<' '<<j<<' '<<val<<endl;
					if(A[i][j]=='*')
					{
						if(!ct1&&!ct2)ins(now,val);//0000
					}
					else if(!ct1&&!ct2)//1001
					{
						if(A[i+1][j]=='.'&&A[i][j+1]=='.')ins(now+(9<<((j-1)*2)),val);
					}
					else if(ct1&&!ct2)//移位(注意j,j-1都右移了) 
					{
						if(A[i+1][j]=='.')ins(now,val);
						if(A[i][j+1]=='.')ins(now-(1<<((j-1)*2))*ct1+(1<<(j*2))*ct1,val);
					}
					else if(!ct1&&ct2)
					{
						if(A[i+1][j]=='.')ins(now-(1<<(j*2))*ct2+(1<<((j-1)*2))*ct2,val);
						if(A[i][j+1]=='.')ins(now,val);
					}		
					else if(ct1==1&&ct2==1)//括号序大概这样:xxx((xxx))xxx(显示的括号匹配),而要变为:xxxx()x(之前的变了) 
					{
						int k=1;
						for(int a=j+1;a<=n;a++)
						{
							int p=(now>>(2*a))&3;
							if(p==1)k++;
							if(p==2)k--;
							if(!k)
							{
								ins(now-(1<<(j*2))-(1<<((j-1)*2))-(1<<(a*2)),val);	//将第a位2->1;
								break; 
							} 
						} 
					}	
					else if(ct1==2&&ct2==2)
					{
						int k=-1;
						for(int a=j-2;a>=0;a--)
						{
							int p=(now>>(2*a))&3;
							if(p==1)k++;
							if(p==2)k--;
							if(!k)
							{
								ins(now-(1<<(j*2))*2-(1<<((j-1)*2))*2+(1<<(a*2)),val);	//将第a位1->2;
								break; 
							} 
						} 
					}	
					else if(ct1==2&&ct2==1)//x(xx()x)xx->x(xxxxx)xx
					{
						ins(now-(1<<(j*2))-(1<<((j-1)*2))*2,val);
					}	
					else if(edx==i&&edy==j)
					{
					//	cout<<val<<endl; 
						ans+=val;	
						
					}
				} 
				
			} 
		} 
		cout<<ans;
		return 0;
	}
}
#undef int
int main()
{
	acac::main();
	return 0;
}

才学dp,转移没看出问题:(

2024/6/13 12:16
加载中...