编程练习-传染病、感染问题

题目描述

小码哥正在研究传染病的相关知识,现在遇到了这么—个问题:
有一个长为n,宽为m,高为k (层数)的长方体,它可以看成n x m ×k个1x1×1大小的单位正方体。每个单位正方体都有一个字符。"”表示该位置防疫措施不好,如果被传染了就会感染病毒。”#”表示该区人民防疫措施良好,永远不会感染病毒(甚至都不会成为病毒的携带者)。
现在在长方体的最顶层(层号为1)某个位置,因实验室泄露爆发了病毒。每过一个单位时间,病毒将扩散至周围6个方向的地区。如果某个地区为”#”,那么一定不会被感染并且不会携带病毒同时也不会传播病毒。(但如果这个地方存在泄露的实验室,那么哪怕防疫措施再好也会被感染以及传播病毒)
现在小码哥需要知道,假如第一层坐标为(a,g)的实验室泄露了病毒,那么最多会有多少区域被感染。

输入格式:第一行三个正整数k,n,m ( k, n, m ≤10 )
接下来k层,每层n行,每行m个字符,表示长方体每个单位的状态
最后一行两个正整数x,y ( z ≤n,y≤m )表示发生泄漏的实验室的坐标(这个实验室在第一层)
输出格式:按题目要求输出一行一个整数表示答案。

输入
3 3 3
.#.
###
##.
.##
###
##.



1 1

输出: 13

解题思路

  1. 解法一:暴力扫描
  • flag标记变量记录是否有新的感染发生
  • while(1) 无限循环,直到没有新的感染发生
  • 每一层横向+纵向扫描,层与层之间扫描
#include<bits/stdc++.h> 
using namespace std;
char sites[13][13][13];
int pp[13][13][13]={0};
int main( )
{
    int k,n,m,x,y,count=0;
    char site_c;
    cin>>k>>n>>m;
    for(int i=0;i<k;++i){
        for(int j=0;j<n;++j){
            for(int h=0;h<m;++h){
                cin>>site_c;
                sites[i][j][h]=site_c;
            }
        }
    }
    cin>>x>>y;
    sites[0][x-1][y-1]='x';// 初始感染位置
    int flag=1;// 标记是否还有感染发生

    while(1){
        flag=1;
        for(int i=0;i<k;++i){
            // 每层横向扫描
            for(int j=0;j<n;++j){
                for(int h=0;h<m;++h){
                    if(sites[i][j][h]=='x'){
                        if(h-1>=0){
                            if(sites[i][j][h-1]=='.'){
                                pp[i][j][h-1]=1;
                                flag=0;
                            }
                        }
                        if(h+1<m){
                            if(sites[i][j][h+1]=='.'){
                                pp[i][j][h+1]=1;
                                flag=0;
                            }
                        }
                    }
                    
                }
            }
            // 每层纵向遍历
            for(int j=0;j<n;++j){
                for(int h=0;h<m;++h){
                    if(sites[i][j][h]=='x'){
                        if(j-1>=0){
                            if(sites[i][j-1][h]=='.'){
                                pp[i][j-1][h]=1;
                                flag=0;
                            }
                        }
                        if(j+1<n){
                            if(sites[i][j+1][h]=='.'){
                                pp[i][j+1][h]=1;
                                flag=0;
                            }
                        }
                    }
                    
                }
            }

            // 层次遍历
            for(int j=0;j<n;++j){
                for(int h=0;h<m;++h){
                    if(sites[i][j][h]=='x'){
                        if(i-1>=0){
                            if(sites[i-1][j][h]=='.'){
                                pp[i-1][j][h]=1;
                                flag=0;
                            }
                        }
                        if(i+1<k){
                            if(sites[i+1][j][h]=='.'){
                                pp[i+1][j][h]=1;
                                flag=0;
                            }
                        }
                    }
                      
                }
            }

        }

        // 改变感染位置标识
        for(int i=0;i<k;++i){
            for(int j=0;j<n;++j){
                for(int h=0;h<m;++h){
                    if(pp[i][j][h]==1){
                        sites[i][j][h]='x';
                    }
                }
            }
        }

        if(flag==1) break;

    }
    for(int i=0;i<k;++i){
        for(int j=0;j<n;++j){
            for(int h=0;h<m;++h){
                // cout<<sites[i][j][h]; 
                if(sites[i][j][h]=='x') ++count;
            }
            // cout<<endl;
        }
        // cout<<endl;
    }
    cout<<count;

    return 0;
}
  1. 解法2

深度优先搜索

/*
    深度优先搜索求解
*/
#include <iostream>
#include <vector>
using namespace std;

vector<vector<vector<char>>> vec_g(11,vector<vector<char>>(11,vector<char>(11,' '))); // 记录实验室情况
vector<vector<vector<bool>>> vec_f(11,vector<vector<bool>>(11,vector<bool>(11,false))); // 记录感染情况
// 搜索方向
vector<int> direction_x={1,-1,0,0,0,0};
vector<int> direction_y={0,0,1,-1,0,0};
vector<int> direction_z={0,0,0,0,1,-1};
int ans=0;
void dfs(int z,int x,int y){
    ++ans;
    vec_f[z][x][y]=true;
    for(int i=0;i<6;++i){ // for循环单层6个方向的搜索
        int dx=x+direction_x[i];
        int dy=y+direction_y[i];
        int dz=z+direction_z[i];
        if(dx>=0&&dx<11&&dy>=0&&dy<11&&dz>=0&&dz<11)
            if(vec_f[dz][dx][dy]==false&&vec_g[dz][dx][dy]=='.') dfs(dz,dx,dy);
            
    }

}


int main(){
    int k,n,m,x,y;
    cin>>k>>n>>m;
    for(int i=0;i<k;++i){
        for(int j=0;j<n;++j){
            for(int z=0;z<m;++z){
                // scanf("%c",&vec_g[i][j][z]);
                cin>>vec_g[i][j][z];
            }
        }
    }
    cin>>x>>y;
    dfs(0,x-1,y-1);
    cout<<ans;

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值