URAL Formula 1 ——插头DP

【题目分析】

    一直听说这是插头DP入门题目。

    难到爆炸。

    写了2h,各种大常数,ural垫底。

【代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define maxn 2000005
#define u64 unsigned long long
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
int tot,fac[15],can[50005],top=0,hash[maxn],a[12][12],n,m,ex,ey,b[15];
u64 dp[2][50005];
char s[15];

//void print(int x){F(j,0,m) printf("%d",(x%fac[j+1])/fac[j]);}

void init()
{
	scanf("%d%d",&n,&m);
	F(i,0,n-1){scanf("%s",s);F(j,0,m-1)a[i][j]=s[j]=='*'?1:0;}
	F(i,0,n-1)F(j,0,m-1) if (!a[i][j]) ex=i,ey=j;
//	printf("The end is %d %d
",ex,ey);
	fac[0]=1;F(i,1,14)fac[i]=fac[i-1]*3;tot=fac[m+1]-1;
//	printf("tot is %d
",tot);
	F(i,0,tot)
	{
		int bac=0,flag=1;
		F(j,0,m)
		{
			if ((i%fac[j+1])/fac[j]==1) bac++;
			else if ((i%fac[j+1])/fac[j]==2) bac--;
			if (bac<0) {flag=0;break;}
		}
		if (flag&&bac==0) can[++top]=i,hash[i]=top;
	}
//	printf("All can is %d
",top);
//	F(i,1,top) {printf("%d is can ",can[i]);print(can[i]);printf("
");}
}

void recode(int x)
{F(i,0,m)b[i]=(x%fac[i+1])/fac[i];}

int encode()
{
	int ret=0;
	F(i,0,m) ret+=b[i]*fac[i];
	return ret;
}

int main()
{
	init();
	int now=1,pre=0;
	memset(dp[now],0,sizeof dp[now]);
	dp[now][1]=1;
	F(i,0,n-1)
	F(j,0,m-1)
	{
		now^=1;pre^=1;
		memset(dp[now],0,sizeof dp[now]);
		if (a[i][j])
		{
			F(s,1,top) if (dp[pre][s])
			{
//				print(can[s]);
				int tmp1=(can[s]%fac[j+1])/fac[j],tmp2=(can[s]%fac[j+2])/fac[j+1];
				if (!tmp1&&!tmp2)
				{
					dp[now][s]+=dp[pre][s];
//					printf(" to %d ",s); print(can[s]); printf("
");
				}
			}
		}
		else
		{
			F(s,1,top) if (dp[pre][s])
			{
//				print(can[s]); printf("
");
				int tmp1=(can[s]%fac[j+1])/fac[j],tmp2=(can[s]%fac[j+2])/fac[j+1],tmp=can[s];
				if (!tmp1&&!tmp2)
				{
					tmp+=1*fac[j];
					tmp+=2*fac[j+1];
					dp[now][hash[tmp]]+=dp[pre][s];
//					printf(" to %d ",hash[tmp]); print(tmp); printf("
");
				}
				else if (!tmp1)
				{
					dp[now][hash[tmp]]+=dp[pre][s];
//					printf(" to %d ",hash[tmp]); print(tmp); printf("
");
					tmp-=tmp1*fac[j]; tmp-=tmp2*fac[j+1];
					tmp+=tmp2*fac[j];
					dp[now][hash[tmp]]+=dp[pre][s];
//					printf(" to %d ",hash[tmp]); print(tmp); printf("
");
				}
				else if (!tmp2)
				{
					dp[now][hash[tmp]]+=dp[pre][s];
//					printf(" to %d ",hash[tmp]); print(tmp); printf("
");
					tmp-=tmp1*fac[j]; tmp-=tmp2*fac[j+1];
					tmp+=tmp1*fac[j+1];
					dp[now][hash[tmp]]+=dp[pre][s];
//					printf(" to %d ",hash[tmp]); print(tmp); printf("
");
				}
				else if (tmp1==2&&tmp2==2)
				{
					recode(tmp);
					int pos=0,bac=0;
					D(z,j-1,0)
					{
						if (b[z]==2) bac++;
						if (b[z]==1) bac--;
						if (b[z]==1&&bac==-1) {pos=z;break;}
					}
					b[j]=b[j+1]=0;
					b[pos]=2;
					tmp=encode();
					dp[now][hash[tmp]]+=dp[pre][s];
//					printf(" to %d ",hash[tmp]); print(tmp); printf("
");
				}
				else if (tmp1==1&&tmp2==1)
				{
					recode(tmp);
					int pos=0,bac=0;
					F(z,j+2,n)
					{
						if (b[z]==1) bac++;
						if (b[z]==2) bac--;
						if (b[z]==2&&bac==-1) {pos=z;break;}
					}
					b[j]=b[j+1]=0;
					b[pos]=1;
					tmp=encode();
					dp[now][hash[tmp]]+=dp[pre][s];
//					printf(" to %d ",hash[tmp]); print(tmp); printf("
");
				}
				else if (tmp1==2&&tmp2==1)
				{
					tmp-=tmp1*fac[j];
					tmp-=tmp2*fac[j+1];
					dp[now][hash[tmp]]+=dp[pre][s];
//					printf(" to %d ",hash[tmp]); print(tmp); printf("
");
				}
				else if (tmp1==1&&tmp2==2&&i==ex&&j==ey)
				{
					tmp-=tmp1*fac[j];
					tmp-=tmp2*fac[j+1];
					dp[now][hash[tmp]]+=dp[pre][s];
//					printf(" to %d ",hash[tmp]); print(tmp); printf("
");
				}
			}
		}
		if (j==m-1)
		{
			now^=1; pre^=1;
			memset(dp[now],0,sizeof dp[now]);
			F(s,1,top) if (dp[pre][s])
			{
//				print(can[s]);
				recode(can[s]);
				if (b[m]!=0)
				{
//					printf(" can't
");
					continue;
				}
				D(i,m,1) b[i]=b[i-1];
				b[1]=0;
				int tmp=encode();
				if (!hash[tmp]) {continue;}
				dp[now][hash[tmp]]+=dp[pre][s];
//				printf(" rev to %d ",hash[tmp]); print(tmp); printf("
");
			}
		}
//		printf("
");
	}
	printf("%llu
",dp[now][1]);
}

  

原文地址:https://www.cnblogs.com/SfailSth/p/6435430.html