题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3085
思路:双向广搜,每次从M出发,搜三步,从G出发,搜一步,然后就是判断是否走到对方已经走过的格子,至于魔王的判断,可以用曼哈顿距离。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 #define MAXN 1000 8 9 struct Node{ 10 int x,y; 11 Node(){} 12 Node(int xx,int yy):x(xx),y(yy){}; 13 }mm,gg,zz[2]; 14 15 bool mark[MAXN][MAXN][2]; 16 int n,m,step; 17 char map[MAXN][MAXN]; 18 int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; 19 queue<pair<int,int> >que[2]; 20 21 bool Judge(int x,int y) 22 { 23 if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!='X'){ 24 for(int i=0;i<2;i++){ 25 if((abs(x-zz[i].x)+abs(y-zz[i].y))<=2*step)return false; 26 } 27 return true; 28 } 29 return false; 30 } 31 32 bool bfs(int num) 33 { 34 int size=que[num].size(); 35 while(size--){ 36 int x=que[num].front().first; 37 int y=que[num].front().second; 38 que[num].pop(); 39 if(!Judge(x,y))continue; 40 for(int i=0;i<4;i++){ 41 int xx=x+dir[i][0]; 42 int yy=y+dir[i][1]; 43 if(Judge(xx,yy)){ 44 if(!mark[xx][yy][num]){ 45 if(mark[xx][yy][num^1])return true; 46 mark[xx][yy][num]=true; 47 que[num].push(make_pair(xx,yy)); 48 } 49 } 50 } 51 } 52 return false; 53 } 54 55 56 int Solve() 57 { 58 memset(mark,false,sizeof(mark)); 59 while(!que[0].empty())que[0].pop(); 60 while(!que[1].empty())que[1].pop(); 61 que[0].push(make_pair(mm.x,mm.y)); 62 que[1].push(make_pair(gg.x,gg.y)); 63 mark[mm.x][mm.y][0]=mark[gg.x][gg.y][1]=true; 64 step=0; 65 while(!que[0].empty()||!que[1].empty()){ 66 step++; 67 if(bfs(0))return step;//mm要搜三步 68 if(bfs(0))return step; 69 if(bfs(0))return step; 70 if(bfs(1))return step; 71 } 72 return -1; 73 } 74 75 76 77 int main() 78 { 79 int _case,index; 80 scanf("%d",&_case); 81 while(_case--){ 82 scanf("%d%d",&n,&m); 83 index=0; 84 for(int i=0;i<n;i++){ 85 scanf("%s",map[i]); 86 for(int j=0;j<m;j++){ 87 if(map[i][j]=='M')mm=Node(i,j); 88 else if(map[i][j]=='G')gg=Node(i,j); 89 else if(map[i][j]=='Z')zz[index++]=Node(i,j); 90 } 91 } 92 printf("%d ",Solve()); 93 } 94 return 0; 95 }