贪吃蛇,首要问题是如何记录蛇的状态,蛇头,蛇身中每个点与上一点之间的方向关系。
故可以用哈希来定义状态,这里学习了别人的hash方法。每次找到当前点与前面一点的方向关系来确定hash返回值
剩下的就是直接BFS,每次更新新蛇一定要注意蛇的长度是多少,如果蛇的长度大于等于3,那么碰到蛇的尾部是合法的
如果蛇的长度小于3,那么碰到蛇尾是不合法的
另外注意移动过程中那种情况下都不能碰到蛇身
利用蛇前后位置的一一替换的对应关系,移动蛇身。根据hash判重就可以
每组数据后要清空队列
另外不知道为什么直接用int front,rear; Q【MAXN】会RE。
故可以用哈希来定义状态,这里学习了别人的hash方法。每次找到当前点与前面一点的方向关系来确定hash返回值
剩下的就是直接BFS,每次更新新蛇一定要注意蛇的长度是多少,如果蛇的长度大于等于3,那么碰到蛇的尾部是合法的
如果蛇的长度小于3,那么碰到蛇尾是不合法的
另外注意移动过程中那种情况下都不能碰到蛇身
利用蛇前后位置的一一替换的对应关系,移动蛇身。根据hash判重就可以
每组数据后要清空队列
另外不知道为什么直接用int front,rear; Q【MAXN】会RE。
#include <map>
#include <set>
#include <list>
#include <cmath>
#include<cctype>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b)
{
return a % b == 0 ? b : gcd(b, a % b);
}
char G[20][20];
int vis[20000000];
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
int len;
int N,M;
int e_x,e_y,s_x,s_y;
int ans;
struct node
{
int x[11],y[11];//存蛇的每一个点的横纵坐标
int dist;
}s;
queue<node>Q;
int get_nextdir(int cur,int pre,node s)
{
for (int d=0;d<4;d++)
{
int nx=s.x[pre]+dx[d];
int ny=s.y[pre]+dy[d];
if (nx==s.x[cur] && ny==s.y[cur]) return d;
}
}
int hash(int x,int y,node s)
{
int Hash=x*M+y;
for (int i=1;i<len;i++)
{
Hash=Hash*4+get_nextdir(i,i-1,s);
}
return (Hash%20000000);
}
void read()
{
len=0;
ans=-1;
memset(G,0,sizeof(G));
memset(vis,0,sizeof(vis));
for (int i=0;i<N;i++)
scanf("%s",G[i]);
for (int i=0;i<N;i++)
for (int j=0;j<M;j++)
{
if (G[i][j]=='@') {e_x=i;e_y=j;}
if (isdigit(G[i][j]))
{
if (G[i][j]=='1') {s_x=i;s_y=j;}
s.x[G[i][j]-'1']=i;
s.y[G[i][j]-'1']=j;
G[i][j]='.';
len++;
}
}
s.dist=0;
int T=hash(s_x,s_y,s);
vis[T]=1;
Q.push(s);
//show();
}
void bfs()
{
while (!Q.empty())
{
node u=Q.front();
Q.pop();
if (u.x[0]==e_x && u.y[0]==e_y) {ans=u.dist;return ;}
int x=u.x[0],y=u.y[0];
for (int d=0;d<4;d++)
{
int nx=x+dx[d];
int ny=y+dy[d];
if (nx<0 || nx>=N || ny<0 || ny>=M || G[nx][ny]=='#') continue;
bool flag=false;
if (len>=3)
{
for (int i=1;i<len-1;i++)
if (nx==u.x[i] && ny==u.y[i]) {flag=true;break;}
if (flag) continue;
node s;
s.x[0]=nx;s.y[0]=ny;
for (int i=1;i<len;i++)
{
s.x[i]=u.x[i-1];
s.y[i]=u.y[i-1];
}
LL T=hash(nx,ny,s);
if (!vis[T])
{
vis[T]=1;
s.dist=u.dist+1;
Q.push(s);
}
}
else
{
for (int i=1;i<=len-1;i++)//注意和上一种i<len-1不同
if (nx==u.x[i] && ny==u.y[i]) {flag=true;break;}
if (flag) continue;
node s;
s.x[0]=nx;s.y[0]=ny;
for (int i=1;i<len;i++)
{
s.x[i]=u.x[i-1];
s.y[i]=u.y[i-1];
}
LL T=hash(nx,ny,s);
if (!vis[T])
{
vis[T]=1;
s.dist=u.dist+1;
Q.push(s);
}
}
}
}
}
int main()
{
//freopen("sample.txt","r",stdin);
int kase=1;
while (scanf("%d%d",&N,&M)!=EOF)
{
read();
bfs();
printf("Case #%d: %d\n",kase++,ans);
while (!Q.empty())Q.pop();
}
return 0;
}