很明显的双向广搜,每次从M的方向搜3步,从G的方向搜1步,然后判断是否走到对方已经走过的格子即可。至于魔王的判断,直接用曼哈顿距离判断就可以了。
1 #include <string.h> 2 #include <stdio.h> 3 #include <queue> 4 #include <stdlib.h> 5 #define MAXN 805 6 struct pnt{ 7 int x,y; 8 pnt(){}; 9 pnt(int _x,int _y):x(_x),y(_y){} 10 }gst[2],st,en,q[2][MAXN*MAXN]; 11 int front[2],rear[2]; 12 int dx[4]={1,0,0,-1},dy[4]={0,1,-1,0}; 13 int cas,n,m,sp[2],step,gsts; 14 char mz[MAXN][MAXN]; 15 //判断是否已经是ghost的地盘,直接用曼哈顿距离判就可以了 16 int hasgst(int x,int y,int tm){ 17 for(int i=0;i<2;i++)if(abs(x-gst[i].x)+abs(y-gst[i].y)<=tm*2)return 1; 18 return 0; 19 } 20 int bfs(int cur,int st,char now,char op){ 21 for(int k=0;k<st;k++){ 22 int ost=0,nst=0; 23 while(ost++<sp[cur]){ 24 pnt p=q[cur][front[cur]++]; 25 if(hasgst(p.x,p.y,step))continue; 26 for(int i=0;i<4;i++){ 27 int nx=p.x+dx[i],ny=p.y+dy[i]; 28 if(mz[nx][ny]=='X'||mz[nx][ny]==now||hasgst(nx,ny,step))continue; 29 if(mz[nx][ny]==op)return 1; 30 mz[nx][ny]=now; 31 q[cur][rear[cur]++]=pnt(nx,ny); 32 nst++; 33 } 34 } 35 sp[cur]=nst; 36 } 37 return 0; 38 } 39 //双广,M走3步,G走1步 40 int db_bfs(){ 41 q[0][front[0]=rear[0]=0]=st,rear[0]++; 42 q[1][front[1]=rear[1]=0]=en,rear[1]++; 43 sp[0]=sp[1]=1,step=0; 44 while(front[0]<rear[0]&&front[1]<rear[1]) 45 if(step++,bfs(1,1,'G','M')||bfs(0,3,'M','G'))return step; 46 return -1; 47 } 48 int main(){ 49 scanf("%d",&cas); 50 while(cas--){ 51 scanf("%d%d",&n,&m); 52 gsts=0; 53 for(int i=1;i<=n;i++){ 54 scanf("%s",mz[i]+1); 55 for(int j=1;j<=m;j++){ 56 if(mz[i][j]=='Z')gst[gsts++]=pnt(i,j); 57 else if(mz[i][j]=='M')st=pnt(i,j); 58 else if(mz[i][j]=='G')en=pnt(i,j); 59 } 60 } 61 for(int i=0;i<=n;i++)mz[i][0]=mz[i][m+1]='X'; 62 for(int i=0;i<=m;i++)mz[0][i]=mz[n+1][i]='X'; 63 printf("%d\n",db_bfs()); 64 } 65 return 0; 66 }