YYR在洞穴中遭遇毒气,必须赶紧逃离此是非之地,怎奈毒气亦会扩散,且向四周绵延,即扩散的毒气继续扩散。给出YYR当前坐标和毒气坐标以及洞口坐标,判断YYR是否能够逃离此是非之地,人命关天啊!
用两个队列q和gas保存bfs当前层次YYR能到达的地方以及能够继续扩散的毒气坐标。这是个比较棘手的问题。也就是说bfs每深入一层,这一层的节点都应该在毒气状态相同的情况下处理。反之毒气也是每一层如此。程序中有两个while(cur_size--)就是处理这个问题的。
#include <iostream>
#include <queue>
using namespace std;
const int N = 1005;
struct pos
{
int row; int col;
int minute;
pos() {}
pos(int rr,int cc): row(rr),col(cc) {}
}to_push;
queue<pos> q,gas;
char map[N][N];
int visit[N][N],m,n,end_row,end_col;
int row_move[4] = {0,1,0,-1},col_move[4] = {1,0,-1,0};
void gas_move() // 毒气扩散至周围,当然有墙时会挡住毒气向该方向扩散
{
int cur_size = gas.size();
while(cur_size--)
{
int cur_row = gas.front().row,cur_col = gas.front().col; gas.pop();
if(cur_row-1 >= 0 && map[cur_row-1][cur_col] == '.' && !visit[cur_row-1][cur_col])
{
map[cur_row-1][cur_col] = 'D';
visit[cur_row-1][cur_col] = 1;
gas.push(pos(cur_row-1,cur_col));
}
if(cur_row+1 < m && map[cur_row+1][cur_col] == '.' && !visit[cur_row+1][cur_col])
{
map[cur_row+1][cur_col] = 'D';
visit[cur_row+1][cur_col] = 1;
gas.push(pos(cur_row+1,cur_col));
}
if(cur_col-1 >= 0 && map[cur_row][cur_col-1] == '.' && !visit[cur_row][cur_col-1])
{
map[cur_row][cur_col-1] = 'D';
visit[cur_row][cur_col-1] = 1;
gas.push(pos(cur_row,cur_col-1));
}
if(cur_col+1 < n && map[cur_row][cur_col+1] == '.' && !visit[cur_row][cur_col+1])
{
map[cur_row][cur_col+1] = 'D';
visit[cur_row][cur_col+1] = 1;
gas.push(pos(cur_row,cur_col+1));
}
}
}
void bfs() // BFS
{
while(!q.empty())
{
int cur_size = q.size();
gas_move();
while(cur_size--){ // 处理当前层次的YYR可以到达的地点
pos temp = q.front(); q.pop();
if(temp.row == end_row && temp.col == end_col)
{
cout<<temp.minute <<endl;
return;
}
for(int i = 0;i < 4;++i)
{
to_push.row = temp.row + row_move[i];
to_push.col = temp.col + col_move[i];
if(to_push.row < 0 || to_push.row >= m || to_push.col < 0 || to_push.col >= n) continue;
if((map[to_push.row][to_push.col] == '.' || map[to_push.row][to_push.col] == 'E') && !visit[to_push.row][to_push.col])
{
to_push.minute = temp.minute + 1;
visit[to_push.row][to_push.col] = 1;
q.push(to_push);
}
}
}
}
cout<<"YYR is extremely dangerous!"<<endl;
}
int main()
{
while(cin>>m>>n && m && n)
{
for(int i = 0;i < m;++i)
{
for(int j = 0;j < n;++j)
{
cin>>map[i][j]; visit[i][j] = 0;
if(map[i][j] == 'D') {
to_push.row = i; to_push.col = j; visit[i][j] = 1; // 毒气源坐标
gas.push(to_push);
}
else if(map[i][j] == 'P') {
to_push.row = i; to_push.col = j; visit[i][j] = 1; //YYR起始坐标
to_push.minute = 0;
q.push(to_push);
}
else if(map[i][j] == 'E') {
end_row = i; end_col = j; // 洞口坐标
}
}
}
bfs();
while(!q.empty()) q.pop();
while(!gas.empty()) gas.pop();
}
return 0;
}