1605: 逛中南(PIPIPOJ)
题目描述
PIPI和小伙伴们考研初试结束了,想要去中南校本部逛一逛,但他们每个人起始的位置不同,中南校本部可以看成一个m*n的网格,PIPI和小伙伴们分别在不同的位置,中南有楼房也有空地,楼房不能走,空地可走,他们每个人每秒都可以沿上下左右走一步,请问最少多少时间能有两个人相遇?
输入
多组输入。
每组第一行输入迷宫的大小m和n(1<=m,n<=1000)。
接下来m行每行n个字符,*代表人,#代表楼房,-代表空地。
输出
输出有两个人相遇的最少时间。
如果无论多久都不能有两个人相遇,输出-1。
样例输入
2 3
#
2 3
#
-#-
样例输出
2
-1
提示信息
每个人在每秒都可以选择原地不动
题解1(C++版本)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
const int dx[] = {0,1,0,-1}; // 这里不要添加{0,0}这个,因为在原地等待的累加时间,可以用对方到达这点的时间来替换,这两者是相同的,不然这点会被重复访问很多次,导致死循环
const int dy[] = {1,0,-1,0};
char mp[N][N];
int m, n;
int vis[N][N];
struct node{
int x,y,step;
}now;
queue<node> q;
bool check(int x, int y){
if(x < 1 || x > m || y < 1 || y > n || mp[x][y] == '#') return false;
return true;
}
int bfs(){
while(!q.empty()){
now = q.front(); q.pop();
for(int i = 0; i < 4; i++){
int tx = now.x + dx[i];
int ty = now.y + dy[i];
if(!check(tx, ty)) continue;
if(!vis[tx][ty]) { // 这点没有被任何人访问过
vis[tx][ty] = vis[now.x][now.y];
}else if(vis[tx][ty] == vis[now.x][now.y]) continue; //这点被自己访问过
else return now.step + 1; //这点被对方访问过,直接返回答案
q.push({tx, ty, now.step + 1});
}
}
return -1;
}
int main(){
while(~scanf("%d%d", &m, &n)){
memset(vis, 0, sizeof vis);
while(!q.empty()) q.pop();
for(int i = 1; i <= m; i++) scanf("%s", mp[i] + 1);
for(int i = 1, flag = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
if(mp[i][j] == '*'){
vis[i][j] = flag; //用flag的不同值(1:自己,2:对方)来标识双方访问的点
q.push({i,j,0});
flag++;
}
}
}
printf("%d\n", bfs());
}
return 0;
}