要求:M和G被困在迷宫内,迷宫内有人不可走但是鬼可通过的墙,里面有两个鬼Z,这两个鬼每秒走2步,M每秒走3步,G每秒走1步。M和G若碰到Z则会死掉。问M和G是否能遇见,若能遇见,则最短相遇时间多少。
方法:双向bfs 曼哈顿距离 3次bfs
1.M和G一块走,用双向bfs。双向bfs即2个bfs。
2.M走3步,用3次bfs。注意使用3次bfs时,每次只更新同一步的结点,例如a,b,c是第一次的结点,产生了d,e,f的结点。那么更新时只更新a,b,c,新生成的d,e,f用作下一步更新。因此需要num记录当前的队列大小,只更新num大小的结点。
3.G走1步,用1次bfs。
4.Z走2步,因可以过墙,所以直接用曼哈顿距离即可。
5.曼哈顿距离:d(i,j)=|xi-xj|+|yi-yj|。
#include<iostream>
#include<stdio.h>
#include<queue>
#include<map>
#include<string.h>
#include<math.h>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std ;
int m , n ;
int step ;
int row[4] = {1 , -1 , 0 , 0} ;
int col[4] = {0 , 0 , -1 , 1} ;
char map1[805][805] ;
int vis[2][805][805] ;
int mx , my ;
int gx , gy ;
int zx1 , zy1 ;
int zx2 , zy2 ;
struct node
{
int x , y ;
} ;
queue <node> q[2] ;
bool bfs(int w)
{
int i , j ;
node a , b ;
int num = q[w].size() ;
while(num --)
{
a = q[w].front() ;
q[w].pop() ;
if(abs(zx1 - a.x) + abs(zy1 - a.y) <= 2 * step
||abs(zx2 - a.x) + abs(zy2 - a.y) <= 2 * step)
continue ;
for(i = 0 ; i < 4 ; i ++)
{
b.x = a.x + row[i] ;
b.y = a.y + col[i] ;
if(b.x < 0 || b.x >= m || b.y < 0 || b.y >= n
|| map1[b.x][b.y] == 'X')
continue ;
if(abs(zx1 - b.x) + abs(zy1 - b.y) <= 2 * step
||abs(zx2 - b.x) + abs(zy2 - b.y) <= 2 * step)
continue ;
if(!vis[w][b.x][b.y])
{
if(vis[1-w][b.x][b.y])
return 1 ;
vis[w][b.x][b.y] = 1 ;
q[w].push(b) ;
//printf("%d %d %d\n" , w , b.x , b.y) ;
}
}
}
return 0 ;
}
void solve()
{
int i , j ;
node a , b ;
zx1 = zy1 = zx2 = zy2 = -1 ;
for(i = 0 ; i < m ; i ++)
for(j = 0 ; j < n ; j ++)
if(map1[i][j] == 'M')
mx = i , my = j ;
else if(map1[i][j] == 'G')
gx = i , gy = j ;
else if(map1[i][j] == 'Z')
{
if(zx1 == -1)
zx1 = i , zy1 = j ;
else
zx2 = i , zy2 = j ;
}
while(!q[0].empty())
q[0].pop() ;
while(!q[1].empty())
q[1].pop() ;
memset(vis , 0 , sizeof(vis)) ;
step = 0 ;
a.x = mx , a.y = my ;
q[0].push(a) ;
a.x = gx , a.y = gy ;
q[1].push(a) ;
vis[0][mx][my] = 1 ;
vis[1][gx][gy] = 1 ;
while(!q[0].empty() || !q[1].empty())
{
step ++ ;
if(bfs(0))
{
printf("%d\n" , step) ;
return ;
}
if(bfs(0))
{
printf("%d\n" , step) ;
return ;
}
if(bfs(0))
{
printf("%d\n" , step) ;
return ;
}
if(bfs(1))
{
printf("%d\n" , step) ;
return ;
}
}
printf("-1\n") ;
}
int main()
{
int i , j ;
int t ;
scanf("%d" , &t) ;
while(t--)
{
scanf("%d%d" , &m , &n) ;
for(i = 0 ; i < m ; i ++)
scanf("%s" , map1[i]) ;
solve() ;
}
}