在这里我们将蛇的状态描述为如下三元组(x,y,sta),其中 (x,y)是蛇头的坐标,state 记录的是身体的状态,由于身体最长为七段,每一段相对于前一段只有上下左右四种状态,仅需要两位表示,则身体所有块的状态最多需要 7×2=14 位二进制数表示,则我们可以构建矩阵vis[x][y][sta] 来保存访问过的状态,以避免重复访问相同的状态,后面的工作就是传统的广搜过程了;
代码很容易看得懂
#include <iostream>
#include <algorithm>
#include <vector>
#include <list>
#include <map>
#include <cstdio>
#include <cstring>
#include <queue>`这里写代码片`
using namespace std;
int vis[21][21][17000];
int fac[15];
int g[21][21];
int **start;
int n,m,len,k;
int dir[4][2]= {{0,1},{1,0},{0,-1},{-1,0}};
struct node
{
int step;
int p[8][2];
node(int sst,int **pp,int s):step(sst)
{
for(int i=0; i<len; i++)
for(int j=0; j<2; j++)
{
p[i][j]=pp[i][j];
}
sta=s;
}
int sta;
};
int getnum(int **p)
{
int sta=0;
for(int i=1; i<len; i++)
{
if(p[i-1][0]+1==p[i][0]&&p[i-1][1]==p[i][1])
{
sta+=0;
}
else if(p[i-1][0]==p[i][0]&&p[i-1][1]+1==p[i][1])
{
sta+=(1*fac[(i-1)*2]+0*fac[(i-1)*2+1]);
}
else if(p[i-1][0]-1==p[i][0]&&p[i-1][1]==p[i][1])
{
sta+=(1*fac[(i-1)*2]+1*fac[(i-1)*2+1]);
}
else if(p[i-1][0]==p[i][0]&&p[i-1][1]-1==p[i][1])
{
sta+=(0*fac[(i-1)*2]+1*fac[(i-1)*2+1]);
}
}
return sta;
}
void init()
{
fac[0]=1;
for(int i=1; i<=14; i++)
{
fac[i]=fac[i-1]*2;
}
}
int bfs()
{
queue<node *> q;
bool flag=true;
for(int i=0; i<len; i++)
{
if(start[i][0]>n||start[i][0]<1||start[i][1]>m||start[i][1]<1||g[start[i][0]][start[i][1]]==1)
{
flag=false;
break;
}
}
if(!flag)
return -1;
if(start[0][0]==1&&start[0][1]==1)
return 0;
q.push(new node(0,start,getnum(start)));
vis[start[0][0]][start[0][1]][getnum(start)]=1;
int time=-1;
while(!q.empty())
{
node *cur=q.front();
q.pop();
if(cur->p[0][0]==1&&cur->p[0][1]==1)
{
time=cur->step;
break;
}
for(int i=0; i<4; i++)
{
int **tempp=new int *[len];
for(int j=0; j<len; j++)
tempp[j]=new int[2];
tempp[0][0]=cur->p[0][0]+dir[i][0];
tempp[0][1]=cur->p[0][1]+dir[i][1];
bool flag1=true;
for(int j=1; j<len; j++)
{
if(tempp[0][0]==cur->p[j][0]&&tempp[0][1]==cur->p[j][1])
{
flag1=false;
break;
}
}
if(!flag1)
continue;
for(int j=1; j<len; j++)
{
tempp[j][0]=cur->p[j-1][0];
tempp[j][1]=cur->p[j-1][1];
}
for(int j=0; j<len; j++)
{
if(tempp[j][0]>n||tempp[j][0]<1||tempp[j][1]>m||tempp[j][1]<1||g[tempp[j][0]][tempp[j][1]])
continue;
}
int sta1=getnum(tempp);
if(!vis[tempp[0][0]][tempp[0][1]][sta1])
{
q.push(new node(cur->step+1,tempp,sta1));
vis[tempp[0][0]][tempp[0][1]][sta1]=1;
}
}
}
return time;
}
int main()
{
start=new int*[8];
for(int i=0; i<8; i++)
start[i]=new int[2];
init();
while(scanf("%d%d%d",&n,&m,&len)&&(len+m+n)!=0)
{
memset(vis,0,sizeof(vis));
memset(g,0,sizeof(g));
for(int i=0; i<len; i++)
scanf("%d%d",&start[i][0],&start[i][1]);
scanf("%d",&k);
for(int i=0; i<k; i++)
{
int x,y;
scanf("%d%d",&x,&y);
g[x][y]=1;
}
int time=bfs();
cout<<time<<endl;
}
}