题目描述
最近新冠病毒疫情非常严重,由于我们国家采取了有力的措施,才没有使疫情进一步的扩大。今天,作为计算机专业的学生,我们来用程序模拟一下各种情况下的新冠病毒传播情况。现在给定一个n * m的网格,每个网格可以有以下三个值之一:
值 0 代表隔离带。
值 1 代表健康人群。
值 2 代表感染人群。
每天,任何与感染人群(在 4 个正方向上)相邻的健康人都会感染。如果遇到隔离带,病毒就会被阻断。输出直到单元格中没有健康人为止所必须经过的最小天数。如果不可能所有人都被感染,输出 -1。
输入
测试数据由多组测试样例组成。第一行输入两个正整数 n ( 1 <= n <= 500 ) 和 m ( 1 <= m <= 500 ),接下来输入n * m个数字,数字均由 0 , 1 ,2构成
输出
每组测试样例,输出直到单元格中没有健康人为止所必须经过的最小天数。如果不可能,输出 -1。
样例输入
3 3
2 1 1
1 1 0
0 1 1
3 3
2 1 1
0 1 1
1 0 1
1 2
0 2
样例输出
4
-1
0
代码
#include <iostream>
#include <queue>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>
#include <cstdlib>
using namespace std;
int n,m;
int s[505][505];
int vis[505][505];
int dir[4][2] = { {-1,0},{0,-1},{1,0},{0,1} };
//怎么定义队列?
// map key - value
// pair 单一的键值对 key value
queue<pair<int,int> > q;
int bfs(){
//初始化答案 ans
int ans = -1;
//判断队列是否为空
while(!q.empty()){
ans ++;
int len = q.size();
for(int i = 0 ; i < len ; i ++){
//先取出队列头部的元素 q.front()取出的元素类型是pair
int x = q.front().first;
int y = q.front().second;
//不要忘记 弹出队头元素
q.pop();
//通过我们取出的x,y来计算 x,y能够在下一天感染到的坐标
for(int j = 0 ; j < 4 ; j ++){
//tx,ty就是 x和y能够感染到的下一个节点
int tx = x + dir[j][0];
int ty = y + dir[j][1];
if(tx >= 0 && ty >= 0 && tx < n && ty < m && vis[tx][ty] == 0 && s[tx][ty] != 0){
//tx ty标记为已访问
vis[tx][ty] = 1;
//感染
s[tx][ty] = 2;
//压入队列
q.push({tx,ty});
}
}
}
}
return ans;
}
int main()
{
// freopen("test.in","r",stdin);
// freopen("test.out","w",stdout);
ios::sync_with_stdio(false);
while(cin >> n >> m){
//如果队列是不空的,先弹光
while(!q.empty()){
q.pop();
}
memset(vis,0, sizeof(vis));
for(int i = 0 ; i < n ; i ++){
for(int j = 0 ; j < m ; j ++){
cin >> s[i][j];
if(s[i][j] == 2){
q.push({i,j});
vis[i][j] = 1;
}
}
}
int ans = bfs();
//判断是否还有健康人
int flag = 0;
for(int i = 0 ; i < n ; i ++){
for(int j = 0 ; j < m ; j ++){
if(s[i][j] == 1){
flag = 1;
break;
}
}
if(flag)
break;
}
if(flag)
cout << -1 << endl;
else
cout << ans << endl;
}
return 0;
}