题目相关
题目链接
一本通 OJ,http://ybt.ssoier.cn:8088/problem_show.php?pid=1191。
题目描述
有一批易感人群住在网格状的宿舍区内,宿舍区为 n*n 的矩阵,每个格点为一个房间,房间里可能住人,也可能空着。在第一天,有些房间里的人得了流感,以后每天,得流感的人会使其邻居传染上流感,(已经得病的不变),空房间不会传染。请输出第 m 天得流感的人数。
输入
第一行一个数字 n,n 不超过100,表示有 n*n 的宿舍房间。
接下来的 n 行,每行 n 个字符,’.’ 表示第一天该房间住着健康的人,’#’ 表示该房间空着,’@’ 表示第一天该房间住着得流感的人。
接下来的一行是一个整数 m,m 不超过 100。
输出
输出第 m 天,得流感的人数。
样例输入
5
....#
.#.@.
.#@..
#....
.....
4
样例输出
16
题目分析
题意分析
一个疾病很容易感染,它的感染方法是从当前病人房间出发,向上、向右、向下、向左,这四个方向进行感染。只要这个房间里有健康的人,就会给感染。如下图所示。要求我们计算,记过若干天后,得病的人数。
数据范围分析
n 不超过100,也就是说,最多有 100*100=10000个房间,也就意味着所有人的感染最大的数据为 1e4。
样例数据分析
我们用输入样例为例,绘制一下每天病人情况。
1、第一天。病人情况如下所示。
....#
.#.@.
.#@..
#....
.....
这样我们知道初始病人数量为 2。
2、第二天。我们从开始的病人房间出发,分四个方向进行感染。病人情况如下所示。
...@#
.#@@@
.#@@.
#.@..
.....
这样我们知道病人数量为 7。
3、第三天。我们从开始的病人房间出发,分四个方向进行感染。病人情况如下所示。
..@@#
.#@@@
.#@@@
#@@@.
..@..
这样我们知道病人数量为 12。
3、第三天。我们从开始的病人房间出发,分四个方向进行感染。病人情况如下所示。
.@@@#
.#@@@
.#@@@
#@@@@
.@@@.
这样我们知道病人数量为 16。
算法设计
从上面的样例数据分析,我们可以知道,要做的事情就是模拟整个感染过程。那么问题就变成如何描述病人感染。这里我们可以参考使用数据结构中的队列(queue)来模拟。这样我们算法可以描述如下:
1、读入数据,并生成第一天病人队列。
2、遍历病人队列,开始四个方向感染病人。
3、队列结束条件:(1)队列里没有新的病人可以感染;(2)感染的天数达到计算要求。
AC 参考代码
#include <iostream>
#include <queue>
using namespace std;
const int MAXN = 100+2;
char room[MAXN][MAXN];//房间描述
typedef struct _POS {
int x; //x坐标
int y; //y坐标
int day; //第几天干扰
} POS;
queue<POS> q;
unsigned long long ans=0;
int main() {
int n;
cin>>n;
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
cin>>room[i][j];
if ('@'==room[i][j]) {
POS t;
t.x = i;
t.y = j;
t.day = 1;
q.push(t);
ans++;
}
}
}
int m;
cin>>m;
//定义感染方向
const int movex[] = { 0, 1, 0, -1};
const int movey[] = {-1, 0, 1, 0};
//开始递推
while (false==q.empty()) {
POS curr = q.front();
q.pop();
//天数到了
if (curr.day>=m) {
break;
}
//感染病人
for (int i=0; i<4; i++) {
int nx = curr.x+movex[i];
int ny = curr.y+movey[i];
//判断这个房间的人能否给感染
if (nx>=0&&nx<n && ny>=0&&ny<n && '.'==room[nx][ny]) {
room[nx][ny] = '@';
ans++;
POS t;
t.x = nx;
t.y = ny;
t.day = curr.day+1;
q.push(t);
}
}
}
cout << ans << endl;
return 0;
}
代码分析
1、如何描述房间。我们使用一个二维字符型数组来描述,参考代码中变量 room 的定义。
2、如何感染病人。参考代码中对变量 movex 和 movey 的定义。
3、遍历过程。退出条件(1),即队列内没有病人,参考 q.empty();退出条件(2),天数达到递推要求,参考 curr.day>=m 这个判断,注意我们是从下标 0 开始使用。
4、如何表示病人是第几天感染的。参考自定义结构体 POS 中的 day 这个变量。