sjy插(座) 头DP是一种解决平面内回路问题的DP,一般用状压解决。不难思考,代码量巨多,分类讨论烦死人。
代码(具体看注释)
很详细了,看不懂的yy一下
#include<cstdio>
#include<iostream>
#include<cstring>
#define MAXN 300010
using namespace std;
int n,m;
int has=299989;
int lstx,lsty;
long long bin[15];
long long tot[2];//状态总数
long long js[2][MAXN];//具体状态的方案数
long long a[2][MAXN];//存储的具体状态是什么
long long mapp[15][15];//地图
long long ans; //答案
int fst[300005];
int nxt[300005]; //哈希表
int las,now;//滚动数组
//qtmdsjyczdp
void add(int zt,long long num)
{
// hash table
int x=zt%has+1;
for(int i=fst[x];i;i=nxt[i])
{
if(a[now][i]==zt)
{
js[now][i]+=num;return ;
}
}
tot[now]++;
nxt[tot[now]]=fst[x];
fst[x]=tot[now];
a[now][tot[now]]=zt;
js[now][tot[now]]=num;
}
void DP()
{
//预处理,0行的状态只有一个,为 0
tot[now]=1;
js[now][1]=1;
a[now][1]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=tot[now];j++)
{
a[now][j]<<=2;//换行时左移一位
}
for(int j=1;j<=m;j++)
{
las=now;
now^=1;//滚动
memset(fst,0,sizeof(fst));//初始化表头
tot[now]=0;
for(int k=1;k<=tot[las];k++)
{
int zt=a[las][k];
int b1=(zt>>(j*2-2))&3;
int b2=(zt>>(j*2))&3;//提取插头状态 b1左插头 b2上插头
long long num=js[las][k];//状态数
if(!mapp[i][j])//不允许走
{
if(!b1&&!b2)add(zt,num);//合法
}
else if(!b1&&!b2)// 0 0
{
if(mapp[i][j+1]&&mapp[i+1][j])//合法
{
add(zt+bin[j-1]+2*bin[j],num); //j-1改为1 j改为2
}
}
else if(!b1&&b2)//b1==0
{
if(mapp[i][j+1])add(zt,num);//左连下 状态不变
if(mapp[i+1][j])add(zt-bin[j]*b2+bin[j-1]*b2,num);//左连右 j j-1互换
}
else if(b1&&!b2)//同上
{
if(mapp[i][j+1])add(zt+bin[j]*b1-bin[j-1]*b1,num);
if(mapp[i+1][j])add(zt,num);
}
else if(b1==1&&b2==1)//同左插头 强行掰过来(滑稽)
{
int kl=1;
for(int kk=j+1;kk<=m;kk++)
{
if(((zt>>(kk*2))&3)==1)kl++;
if(((zt>>(kk*2))&3)==2)kl--;
if(!kl)
{
add(zt-bin[j]-bin[j-1]-bin[kk],num);
break;
}
}
}
else if(b1==2&&b2==2)//同上
{
int kl=1;
for(int kk=j-2;kk>=0;kk--)
{
if(((zt>>(kk*2))&3)==1)kl--;
if(((zt>>(kk*2))&3)==2)kl++;
if(!kl)
{
add(zt-2*bin[j]-2*bin[j-1]+bin[kk],num);
break;
}
}
}
else if(b1==2&&b2==1)add(zt-2*bin[j-1]-bin[j],num);//直接消消乐
else if(i==lstx&&j==lsty)ans+=num;//统计答案
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j) {
char ch=getchar();
while(ch!='*'&&ch!='.') ch=getchar();
if(ch=='.') mapp[i][j]=1,lstx=i,lsty=j;// lst表示最后可走的点
}
bin[0]=1;
for(int i=1;i<=12;i++)//预处理4进制
bin[i]=bin[i-1]<<2;
DP();
printf("%lld",ans);
return 0;
}
再给一份没有注释的(你懂的)
#include<cstdio>
#include<iostream>
#include<cstring>
#define MAXN 300010
using namespace std;
int n,m;
int has=299989;
int lstx,lsty;
long long bin[15];
long long tot[2];
long long js[2][MAXN];
long long a[2][MAXN];
long long mapp[15][15];
long long ans;
int fst[300005];
int nxt[300005];
int las,now;
void add(int zt,long long num)
{
//cout<<zt<<endl;
int x=zt%has+1;
for(int i=fst[x];i;i=nxt[i])
{
if(a[now][i]==zt)
{
js[now][i]+=num;return ;
}
}
tot[now]++;
nxt[tot[now]]=fst[x];
fst[x]=tot[now];
a[now][tot[now]]=zt;
js[now][tot[now]]=num;
}
void DP()
{
tot[now]=1;
js[now][1]=1;
a[now][1]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=tot[now];j++)
{
a[now][j]<<=2;
}
for(int j=1;j<=m;j++)
{
las=now;
now^=1;
memset(fst,0,sizeof(fst));
tot[now]=0;
for(int k=1;k<=tot[las];k++)
{
int zt=a[las][k];
int b1=(zt>>(j*2-2))&3;
int b2=(zt>>(j*2))&3;
long long num=js[las][k];
if(!mapp[i][j])
{
if(!b1&&!b2)add(zt,num);
}
else if(!b1&&!b2)
{
if(mapp[i][j+1]&&mapp[i+1][j])
{
add(zt+bin[j-1]+2*bin[j],num);
}
}
else if(!b1&&b2)
{
//cout<<"c";
if(mapp[i][j+1])add(zt,num);
if(mapp[i+1][j])add(zt-bin[j]*b2+bin[j-1]*b2,num);
}
else if(b1&&!b2)
{
if(mapp[i][j+1])add(zt+bin[j]*b1-bin[j-1]*b1,num);
if(mapp[i+1][j])add(zt,num);
}
else if(b1==1&&b2==1)
{
int kl=1;
for(int kk=j+1;kk<=m;kk++)
{
if(((zt>>(kk*2))&3)==1)kl++;
if(((zt>>(kk*2))&3)==2)kl--;
if(!kl)
{
add(zt-bin[j]-bin[j-1]-bin[kk],num);
break;
}
}
}
else if(b1==2&&b2==2)
{
int kl=1;
for(int kk=j-2;kk>=0;kk--)
{
if(((zt>>(kk*2))&3)==1)kl--;
if(((zt>>(kk*2))&3)==2)kl++;
if(!kl)
{
add(zt-2*bin[j]-2*bin[j-1]+bin[kk],num);
break;
}
}
}
else if(b1==2&&b2==1)add(zt-2*bin[j-1]-bin[j],num);
else if(i==lstx&&j==lsty)ans+=num;
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j) {
char ch=getchar();
while(ch!='*'&&ch!='.') ch=getchar();
if(ch=='.') mapp[i][j]=1,lstx=i,lsty=j;
}
bin[0]=1;
for(int i=1;i<=12;i++)
bin[i]=bin[i-1]<<2;
DP();
printf("%lld",ans);
return 0;
}
odk~~