一本通题解——1191:流感传染

题目相关

题目链接

一本通 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 这个变量。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值