【Ural1519】— Formula1(轮廓线dp)
看这个大佬的博客吧,讲的很详细:传送门
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
#define ll long long
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
const int M=300005;
const int N=15;
int n,m,cnt,idx,mp[N][N],tot[2],bit[N],ex,ey;
int adj[M],nxt[M],to[M];
ll f[2][M],sta[2][M],ans;
char s[N];
inline void calc(ll s,ll num){
int u=s%M;
for(int e=adj[u];e;e=nxt[e]){
if(sta[idx][to[e]]==s){
f[idx][to[e]]+=num;return;
}
}
++tot[idx];
sta[idx][tot[idx]]=s;
f[idx][tot[idx]]=num;
nxt[++cnt]=adj[u];
adj[u]=cnt,to[cnt]=tot[idx];
}
int main(){
for(int i=0;i<N;i++)bit[i]=i<<1;
tot[idx]=1,f[idx][1]=1;
n=read(),m=read();
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=m;j++){
mp[i][j]=(s[j]=='.');
if(s[j]=='.')ex=i,ey=j;
}
}
for(int i=1;i<=n;i++){
for(int k=1;k<=tot[idx];k++)sta[idx][k]<<=2;
for(int j=1;j<=m;j++){
memset(adj,0,sizeof(adj));
cnt=0,idx^=1;
tot[idx]=0;
for(int k=1;k<=tot[idx^1];k++){
ll s=sta[idx^1][k];
ll num=f[idx^1][k];
int p=(s>>bit[j-1])%4;
int q=(s>>bit[j])%4;
if(!mp[i][j]){
if(p+q==0)calc(s,num);
}
else if(p+q==0){
if(!mp[i+1][j]||!mp[i][j+1])continue;
s=s+(1<<bit[j-1])+2*(1<<bit[j]);
calc(s,num);
}
else if(!p&&q){
if(mp[i][j+1])calc(s,num);
if(mp[i+1][j]){
s=s+q*(1<<bit[j-1])-q*(1<<bit[j]);
calc(s,num);
}
}
else if(p&&!q){
if(mp[i+1][j])calc(s,num);
if(mp[i][j+1]){
s=s-p*(1<<bit[j-1])+p*(1<<bit[j]);
calc(s,num);
}
}
else if(p+q==2){
int b=1;
for(int t=j+1;t<=m;t++){
int v=(s>>bit[t])%4;
if(v==1)b++;
if(v==2)b--;
if(!b){
s=s-(1<<bit[t]);
break;
}
}
s=s-(1<<bit[j-1])-(1<<bit[j]);
calc(s,num);
}
else if(p+q==4){
int b=1;
for(int t=j-2;t;t--){
int v=(s>>bit[t])%4;
if(v==2)b++;
if(v==1)b--;
if(!b){
s=s+(1<<bit[t]);
break;
}
}
s=s-2*(1<<bit[j-1])-2*(1<<bit[j]);
calc(s,num);
}
else if(p==1&&q==2){
if(i==ex&&j==ey)ans+=num;
}
else if(p==2&&q==1){
s=s-2*(1<<bit[j-1])-(1<<bit[j]);
calc(s,num);
}
}
}
}
cout<<ans;
}