1、题目类型:模拟、贪吃蛇游戏、哈希表、BFS。
2、解题思路:题意,给出活动空间大小、蛇身位置、空间中障碍物位置、目标位置,求解蛇的最少移动步数。难点,用进制的哈希对蛇身相对位置的保存。步骤,(1)根据输入记录Holedox的位置和stones的位置;(2)对Holedox的位置进行哈希状态压缩,哈希加密方式为Staten=Holedox位置的逐一相对位置的4进制*总行数*总列数+总行数*行位置+列位置(解密方式类似);(3)BFS搜索目标情况,成功解密Holedox‘s head位置为(0,0)返回此时step,否则返回-1。
3、注意事项:哈希的构造方法必须唯一,且在int的控制范围以内否则TLE;BFS中常用变量尽量用全局变量,避免Runtime Error。
4、实现方法:
#pragma warning(disable:4786)
#include < iostream >
#include < queue >
#include < map >
using namespace std;
struct Node
{
int state;
int step;
};
Node Q[ 1000000 ];
int X[ 4 ] = { 0 , 1 , 0 , - 1 };
int Y[ 4 ] = { 1 , 0 , - 1 , 0 };
int R,C,L,state;
int sn[ 9 ][ 2 ],mat[ 30 ][ 30 ];
bool vis[ 6800000 ];
map < int , int > S;
void Init()
{
int i,n,a,b;
for (i = 0 ;i < L;i ++ )
{
scanf( " %d%d " , & sn[i][ 0 ], & sn[i][ 1 ]);
sn[i][ 0 ] -- ;
sn[i][ 1 ] -- ;
}
cin >> n;
memset(mat, 0 , sizeof (mat));
for (i = 0 ;i < n;i ++ )
{
scanf( " %d%d " , & a, & b);
a -- ;
b -- ;
mat[a][b] = 1 ;
}
S.clear();
}
// 获得Holedox相对位置
int GetDir( int now[ 2 ], int pre[ 2 ])
{
if (now[ 1 ] == pre[ 1 ] + 1 )
return 0 ;
if (now[ 1 ] == pre[ 1 ] - 1 )
return 2 ;
if (now[ 0 ] == pre[ 0 ] + 1 )
return 1 ;
if (now[ 0 ] == pre[ 0 ] - 1 )
return 3 ;
return 0 ;
}
bool Judge( int ssn[][ 2 ], int sn[][ 2 ])
{
int i;
if ( ! (ssn[ 0 ][ 0 ] >= 0 && ssn[ 0 ][ 0 ] < R && ssn[ 0 ][ 1 ] >= 0 && ssn[ 0 ][ 1 ] < C && mat[ssn[ 0 ][ 0 ]][ssn[ 0 ][ 1 ]] == 0 ))
return false ;
for (i = 0 ;i < L;i ++ )
{
if (ssn[ 0 ][ 0 ] == sn[i][ 0 ] && ssn[ 0 ][ 1 ] == sn[i][ 1 ])
return false ;
}
return true ;
}
int BFS()
{
int i,j,k,front = 0 ,rear = 0 ;
int head[ 2 ],tsn[ 9 ][ 2 ];
Node tmp;
memset(vis, 0 , sizeof (vis));
tmp.state = state;
tmp.step = 0 ;
Q[rear ++ ] = tmp;
vis[state] = 1 ;
while (front < rear)
{
tmp = Q[front];
front = (front + 1 ) % 1000000 ;
head[ 1 ] = tmp.state % (C * R) % C;
head[ 0 ] = tmp.state % (C * R) / C;
state = tmp.state / (C * R);
sn[ 0 ][ 0 ] = head[ 0 ];
sn[ 0 ][ 1 ] = head[ 1 ];
for (i = 1 ;i < L;i ++ )
{
sn[i][ 0 ] = sn[i - 1 ][ 0 ] + X[state % 4 ];
sn[i][ 1 ] = sn[i - 1 ][ 1 ] + Y[state % 4 ];
state /= 4 ;
}
if (head[ 0 ] == 0 && head[ 1 ] == 0 )
return tmp.step;
for (i = 0 ;i < 4 ;i ++ )
{
tsn[ 0 ][ 0 ] = sn[ 0 ][ 0 ] + X[i];
tsn[ 0 ][ 1 ] = sn[ 0 ][ 1 ] + Y[i];
if (Judge(tsn,sn))
{
state = 0 ;
int s = 1 ;
for (j = 1 ;j < L;j ++ )
{
tsn[j][ 0 ] = sn[j - 1 ][ 0 ];
tsn[j][ 1 ] = sn[j - 1 ][ 1 ];
}
for (k = 1 ;k < L;k ++ )
{
state = state + GetDir(tsn[k],tsn[k - 1 ]) * s;
s *= 4 ;
}
state = state * R * C + tsn[ 0 ][ 0 ] * C + tsn[ 0 ][ 1 ];
if ( ! vis[state])
{
Node N;
N.state = state;
N.step = tmp.step + 1 ;
vis[state] = 1 ;
Q[rear] = N;
rear = (rear + 1 ) % 1000000 ;
}
}
}
}
return - 1 ;
}
void Solve( int ca)
{
int i,s = 1 ;
state = 0 ;
for (i = 1 ;i < L;i ++ )
{
state = state + GetDir(sn[i],sn[i - 1 ]) * s;
s *= 4 ;
}
state = state * R * C + sn[ 0 ][ 0 ] * C + sn[ 0 ][ 1 ];
cout << " Case " << ca ++<< " : " ;
cout << BFS() << endl;
}
int main()
{
int ca = 1 ;
while (scanf( " %d%d%d " , & R, & C, & L))
{
if (R == 0 && C == 0 && L == 0 )
break ;
Init();
Solve(ca ++ );
}
return 0 ;
}