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\n",ex,ey); fac[0]=1;F(i,1,14)fac[i]=fac[i-1]*3;tot=fac[m+1]-1; // printf("tot is %d\n",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\n",top); // F(i,1,top) {printf("%d is can ",can[i]);print(can[i]);printf("\n");} } 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("\n"); } } } else { F(s,1,top) if (dp[pre][s]) { // print(can[s]); printf("\n"); 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("\n"); } else if (!tmp1) { dp[now][hash[tmp]]+=dp[pre][s]; // printf(" to %d ",hash[tmp]); print(tmp); printf("\n"); 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("\n"); } else if (!tmp2) { dp[now][hash[tmp]]+=dp[pre][s]; // printf(" to %d ",hash[tmp]); print(tmp); printf("\n"); 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("\n"); } 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("\n"); } 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("\n"); } 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("\n"); } 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("\n"); } } } 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\n"); 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("\n"); } } // printf("\n"); } printf("%llu\n",dp[now][1]); }