51 计算疫情扩散时间

本文介绍了两个C++编程实现的感染扩散算法,分别使用二维矩阵和队列数据结构来模拟病毒在网格上的传播过程,计算感染天数。
摘要由CSDN通过智能技术生成

(1)方案一

#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;

int getInfectionDays(vector<int>& map) 
{
    int n = sqrt(map.size());
    vector<vector<int>> matrix(n, vector<int>(n)); // 将一维数组转换为二维矩阵
    queue<pair<int, int>> q; // 用队列存储感染区域

    for (int i = 0; i < n; i++) 
    {
        for (int j = 0; j < n; j++) 
        {
            matrix[i][j] = map[i * n + j]; // 将一维数组转换为二维矩阵
            if (matrix[i][j] == 1) q.push({i, j}); // 将感染区域加入队列
        }
    }

    if (q.empty() || q.size() == map.size()) 
    {
        // 判断特殊情况
        return -1;
    }

    int healthy = map.size() - q.size(); // 记录未感染区域数量

    vector<vector<int>> offsets = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 记录四个方向的偏移量

    int day = 0; // 记录感染天数
    while (!q.empty() && healthy > 0) 
    {
        // 当队列不为空且还有未感染区域时,进行循环
        pair<int, int> tmp = q.front(); // 取出队首元素
        q.pop(); // 弹出队首元素
        int x = tmp.first, y = tmp.second; // 获取队首元素的坐标
        day = matrix[x][y] + 1; // 记录感染天数

        for (vector<int>& offset : offsets) 
        {
            // 遍历四个方向
            int newX = x + offset[0]; // 新的横坐标
            int newY = y + offset[1]; // 新的纵坐标

            if (newX < 0 || newX >= n || newY < 0 || newY >= n) continue; // 判断边界

            if (matrix[newX][newY] == 0) 
            {
                // 如果该区域未感染
                healthy--; // 未感染区域数量减一
                matrix[newX][newY] = day; // 标记该区域已感染
                q.push({newX, newY}); // 将该区域加入队列
            }
        }
    }

    return day - 1; // 返回感染天数
}

int main() 
{
    string input;
    getline(cin, input);
    vector<int> map;
    size_t pos = 0;
    string token;
    while ((pos = input.find(",")) != string::npos) 
    {
        // 将输入字符串转换为一维数组
        token = input.substr(0, pos);
        map.push_back(stoi(token));
        input.erase(0, pos + 1);
    }
    map.push_back(stoi(input));
    cout << getInfectionDays(map) << endl; // 输出感染天数
    return 0;
}
(2)方案二

#include <iostream>
#include <sstream>
#include <vector>
#include <queue>
#include <math.h>

using namespace std;

void infect(vector<vector<int>>& grid, int x, int y) 
{
    int n = grid.size();
    int m = grid[0].size();
    vector<vector<int>> directions = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};

    for (auto& dir : directions) 
    {
        int x1 = x + dir[0];
        int y1 = y + dir[1];
        if (x1 >= 0 && x1 < n && y1 >= 0 && y1 < m && grid[x1][y1] == 0) 
        {
            grid[x1][y1] = 1;
        }
    }
}

bool check(vector<vector<int>>& grid) 
{
    int sum = 0;
    for (auto& row : grid) 
    {
        for (int x : row) 
        {
            sum += x;
        }
    }
    int n = grid.size();
    return sum != 0 && sum != n * n;
}

int main() 
{
    string mapString;
    getline(cin, mapString);
    stringstream ss(mapString);
    string item;
    vector<int> nums;
    while (getline(ss, item, ',')) 
    {
        nums.push_back(stoi(item));
    }
    int n = sqrt(nums.size());
    vector<vector<int>> grid(n, vector<int>(n));
    int k = 0;
    for (int i = 0; i < n; i++) 
    {
        for (int j = 0; j < n; j++) 
        {
            grid[i][j] = nums[k];
            k++;
        }
    }
    int day = 0;
    while (check(grid)) 
    {
        queue<vector<int>> virus;
        for (int i = 0; i < n; i++) 
        {
            for (int j = 0; j < n; j++) 
            {
                if (grid[i][j] == 1) 
                {
                    virus.push({i, j});
                }
            }
        }
        while (!virus.empty()) 
        {
            vector<int> pos = virus.front();
            virus.pop();
            infect(grid, pos[0], pos[1]);
        }
        day++;
    }
    day = (day == 0) ? -1 : day;
    cout << day << endl;
    return 0;
}
 

  • 23
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值