昨天晚上,小狼(不想翻译名字了。。)做了一个噩梦,他梦到他和他的女朋友一起掉到迷宫里并且分开来了,更糟糕的是,迷宫里面有两个恶鬼,恶鬼杀人。小狼想知道,他是否可以在恶鬼发现他们之前找到他的女朋友。小狼个他女票可以向四个方向移动,每秒,小狼可以移动三步,女票移动一步。恶鬼是邪恶的,每秒他们会分裂成几部分,占领占领距离两部之内的格子,知道占领迷宫。每秒恶鬼先动,然后小狼和小狼的女票才动,他们遇到恶鬼就会死去。
输入:第一行t,表示测试数量。每组测试开始两个整数表示迷宫大小。接下来n行是迷宫,.可行走,X墙,M小狼,G小狼女朋友,Z恶鬼。
输出:输出相遇需要的最短的时间,不能相见输出-1。
这道题错了很久,最后自己的代码还是没改对,就看网上的同学怎么写,最后嗯,借鉴了然后敲了一遍。就是很麻烦,关于走三次,这个入队的操作很麻烦。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=810;
const int dx[]={0,0,-1,1};
const int dy[]={1,-1,0,0};
char maze[maxn][maxn];
int n,m;
int time;
struct node{
int x,y;
}gg,mm,zz[2];
bool kill(node t)//判断是否不能去
{
if(t.x<1||t.y<1||t.x>n||t.y>m) return false;
for(int i=0;i<2;i++)
if(abs(t.x-zz[i].x)+abs(t.y-zz[i].y)<=2*time||maze[t.x][t.y]=='X'||maze[t.x][t.y]=='\0') return false;
return true;
}
queue<node> q[2],q_z;
bool bfs(int mark,int num,char st,char end)
{
q_z=q[mark];
for(int i=0;i<num;i++)
{
while(!q_z.empty())
{
node a=q_z.front();
q_z.pop();q[mark].pop();
if(!kill(a)) continue;
for(int j=0;j<4;j++)
{
node na=a;
na.x=a.x+dx[j];
na.y=a.y+dy[j];
if(!kill(na)||maze[na.x][na.y]==st) continue;
if(maze[na.x][na.y]==end) return true;//找到组织
maze[na.x][na.y]=st;//就标记为当前的符号
q[mark].push(na);
}
}
q_z=q[mark];
}
return false;
}
int solve()
{
time=0;
while(!q[0].empty()) q[0].pop();
while(!q[1].empty()) q[1].pop();
while(!q_z.empty()) q_z.pop();
q[0].push(mm),q[1].push(gg);//放入信息
while(!q[0].empty()&&!q[1].empty())
{
time++;
bool flag1=bfs(0,3,'M','G');//三步
bool flag2=bfs(1,1,'G','M');//一步
if(flag1||flag2) return time;
}
return -1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
memset(maze,'X',sizeof(maze));
for(int k=0,i=1;i<=n;i++)
{
scanf("%s",maze[i]+1);//空下边界
for(int j=1;j<=m;j++)
{
if(maze[i][j]=='M') mm.x=i,mm.y=j;
if(maze[i][j]=='G') gg.x=i,gg.y=j;
if(maze[i][j]=='Z') zz[k].x=i,zz[k].y=j,k++;
}
}
printf("%d\n",solve());
}
return 0;
}