代码没有找到bug,希望来个大佬帮忙找找,谢谢了!!!
思想跟一般的差不多,只不过是第一个位置存的是竖向的关键点
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int LIM = 300005;
const int HASH = 299989;
int n,m;
int endx,endy;
bool a[20][20];
int h[LIM],nextH[LIM];
int f[2][LIM];
int ans;
int sat[2][LIM],sum[2],now;
void add(int cnt, int num)
{
int hash=cnt%HASH+1; //取hash值
printf("add %d\n",cnt);
// 开链避免哈希冲突
for(int i=h[hash];i;i=nextH[i])
if(sat[now][i]==cnt)
{
f[now][i]+=num; //方案累计
return;
}
//新状态,记录
++sum[now];
nextH[sum[now]]=h[hash];
h[hash]=sum[now];
sat[now][sum[now]]=cnt;
f[now][sum[now]]=num;
}
void work()
{
int i,j,k;
sum[now]=1;
f[now][1]=1;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
int old=now; now=!now; //数组滚动
sum[now]=0;
memset(h,0,sizeof(h));
for(k=1;k<=sum[old];k++)
{
int cnt=sat[old][k]; //状态
int b1=cnt&3; //纵向关键点
int b2=(cnt>>j*2)&3; //横向关键点
int num=f[old][k]; //k状态的方案个数
if(!a[i][j]) //当前位置是障碍
{
if(!b1&&!b2)
add(cnt,num);
}
else if(!b1&&!b2)
{
if(a[i+1][j]&&a[i][j+1])
add(cnt+(1<<j*2)+2,num);
}
else if(!b1&&b2)
{
if(a[i][j+1]) add(cnt+b2-(b2<<j*2),num);
if(a[i+1][j]) add(cnt,num);
}
else if(b1&&!b2)
{
if(a[i][j+1]) add(cnt,num);
if(a[i+1][j]) add(cnt-b1+(b1<<j*2),num);
}
else if(b1==1&&b2==1)
{
int kl=1;
for(int t=j+1;t<=m;t++)
{
if((cnt>>t*2)&3==1) ++kl;
if((cnt>>t*2)&3==2) --kl;
if(kl==0)
{
add(cnt-b1-(b2<<j*2)-(1<<t*2),num);
break;
}
}
}
else if(b1==2&&b2==2)
{
int kl=1;
for(int t=j-1;t>=1;t--)
{
if((cnt>>t*2)&3==1) --kl;
if((cnt>>t*2)&3==2) ++kl;
if(kl==0)
{
add(cnt-b1-(b2<<j*2)+(1<<t*2),num);
break;
}
}
}
else if(b1==2&&b2==1)
add(cnt-b1-(b2<<j*2),num);
else if(b1==1&&b2==2)
{
if(i==endx&&j==endy)
ans+=num;
}
}
}
cout<<ans;
}
int main()
{
int i,j;
char c;
cin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
while((c=getchar())&&c!='.'&&c!='*');
if(c=='.')
{
a[i][j]=1;
endx=i; endy=j;
}
}
work();
return 0;
}