插头DP
Posted segmenttree
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了插头DP相关的知识,希望对你有一定的参考价值。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=12;
const int M=1595323;
const int mod=500009;
int n,m,mp[N+5][N+5];
int p3[N+5],now=0,ex,ey;
ll ans;
int ch(char x){return x==‘*‘||x==‘.‘;}
struct Hash
{
int mak[M],E;
ll dp[M];
int h[mod],nxt[M];
void clear()
{
for(int i=0;i<mod;i++) h[i]=0;
E=0;
return;
}
void add(int pos,ll d)
{
int g=pos%mod;
for(int i=h[g];i;i=nxt[i])
{
if(mak[i]==pos)
{
dp[i]+=d;
return;
}
}
E++;
mak[E]=pos;
dp[E]=d;
nxt[E]=h[g];
h[g]=E;
return;
}
}D[2];
int get(int pos,int x)
{
pos/=p3[x];
return pos%3;
}
void cha(int &pos,int x,int t)
{
int b=get(pos,x);
pos-=p3[x]*b;
pos+=p3[x]*t;
return;
}
void tcol()
{
D[now].clear();
for(int i=1;i<=D[now^1].E;i++)
{
int mas=D[now^1].mak[i];
ll dp=D[now^1].dp[i];
int b=get(mas,m);
if(!b) D[now].add(mas*3,dp);
}
return;
}
void up1(int x,int y)
{
D[now].clear();
for(int i=1;i<=D[now^1].E;i++)
{
int mas=D[now^1].mak[i];
ll dp=D[now^1].dp[i];
int b1=get(mas,y-1),b2=get(mas,y);
if(!b1&&!b2) D[now].add(mas,dp);
}
return;
}
int f1(int mas,int x)
{
vector<int> s;
for(int i=0;i<=m;i++)
{
s.push_back(mas%3);
mas/=3;
}
int d=0;
for(int i=x;i<=m;i++)
{
if(s[i]==1) d++;
if(s[i]==2) d--;
if(d==0) return i;
}
return -1;
}
int f2(int mas,int x)
{
vector<int> s;
for(int i=0;i<=m;i++)
{
s.push_back(mas%3);
mas/=3;
}
int d=0;
for(int i=x;i>=0;i--)
{
if(s[i]==1) d++;
if(s[i]==2) d--;
if(d==0) return i;
}
return -1;
}
void up2(int x,int y)
{
D[now].clear();
for(int i=1;i<=D[now^1].E;i++)
{
int mas=D[now^1].mak[i];
ll dp=D[now^1].dp[i];
int b1=get(mas,y-1),b2=get(mas,y);
if(!b1&&!b2)
{
cha(mas,y-1,1);
cha(mas,y,2);
D[now].add(mas,dp);
}
else if(!b1&&b2)
{
D[now].add(mas,dp);
cha(mas,y,0);
cha(mas,y-1,b2);
D[now].add(mas,dp);
}
else if(b1&&!b2)
{
D[now].add(mas,dp);
cha(mas,y-1,0);
cha(mas,y,b1);
D[now].add(mas,dp);
}
else if(b1==b2)
{
if(b1==1&&b2==1)
{
int d1=f1(mas,y);
cha(mas,y-1,0);
cha(mas,y,0);
cha(mas,d1,1);
D[now].add(mas,dp);
}
else
{
int d2=f2(mas,y-1);
cha(mas,y-1,0);
cha(mas,y,0);
cha(mas,d2,2);
D[now].add(mas,dp);
}
}
else if(b1==2&&b2==1)
{
cha(mas,y-1,0);
cha(mas,y,0);
D[now].add(mas,dp);
}
else if(x==ex&&y==ey)
{
cha(mas,y-1,0),cha(mas,y,0);
if(mas==0) ans+=dp;
}
}
return;
}
int main()
{
p3[0]=1;
for(int i=1;i<=N+1;i++) p3[i]=p3[i-1]*3;
scanf("%d%d",&n,&m);
char w;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
while(!ch(w=getchar()));
mp[i][j]=w==‘*‘?1:0;
if(!mp[i][j]) ex=i,ey=j;
}
}
D[0].add(0,1);
for(int i=1;i<=n;i++)
{
now^=1;
tcol();
for(int j=1;j<=m;j++)
{
now^=1;
if(mp[i][j]) up1(i,j);
else up2(i,j);
}
}
printf("%lld
",ans);
return 0;
}
以上是关于插头DP的主要内容,如果未能解决你的问题,请参考以下文章