病毒在封闭空间的传播时间-题解

55 阅读3分钟

这个问题是一个基于图的广度优先搜索(BFS)问题,我们需要计算病毒感染所有座位上的人所需的时间。我们可以将每个座位视为图中的一个节点,而人与人之间的传播关系则可以视为边。以下是结合代码解决这个问题的步骤:

1. 初始化数据结构

  • dxdy 数组用于表示四个方向的移动(上下左右)。
  • d 数组用于存储每个座位的感染时间,初始化为0。
  • boolean[][] st 用于记录每个座位是否已经被访问过,以避免重复感染。

2. 构建图

  • int[][] dp 存储每个座位上人的感染状态,其中 1 表示未戴口罩,可以直接被感染;2 表示戴了口罩,需要额外的感染时间或被两个方向的人同时感染。
int[][] dp = new int[row_n+1][column_m+1];
for(int i=0;i<row_n;i++){
    for(int j=0;j<column_m;j++){
        dp[i][j] = 1; // 默认为1,表示未戴口罩
        if(seats[i][j] == 1) dp[i][j]++; // 如果戴口罩,增加额外的感染时间
    }
}

3. 广度优先搜索(BFS)

  • 使用 Queue<Pair> 来实现 BFS,从已感染的人开始,逐层扩展直到所有节点都被感染。
  • Pair 类用于存储 BFS 中的节点和对应的感染时间。
class Pair{
    int x,y,d;
    public Pair(int x, int y, int d) {
        super();
        this.x = x;
        this.y = y;
        this.d = d;
    }
}
  • bfs 函数中,我们使用一个队列来存储待处理的节点,每个节点包含其坐标和当前的感染时间。
public static int bfs(int x,int y,int n,int m,int[][] dp){
    boolean[][] st = new boolean[10001][10001];
    Queue<Pair> p = new LinkedList<Pair>();
    Arrays.fill(d, 0);
    p.add(new Pair(x, y, 0));
    int ans = 0;
    while(p.size()>0) {
        Pair pair = p.poll();
        int x2 = pair.x,y2 = pair.y,d = pair.d;
        if(!st[x2][y2]) {
            st[x2][y2] = true;
            ans = Math.max(ans, d); // 更新最大感染时间
            for(int i=0;i<4;i++){
                int x1 = x2 + dx[i],y1 = y2 + dy[i];
                if(x1 >= 0 && x1 < n && y1 < m && y1 >= 0 && dp[x1][y1] > 0){
                    dp[x1][y1] --;
                    if(dp[x1][y1] == 0) {
                        p.add(new Pair(x1, y1, d + 1));
                    }
                }
            }
        }
    }
    return ans;
}

4. 计算最大感染时间

  • bfs 函数中,我们维护一个 ans 变量来记录最大的感染时间。
  • 每次访问一个新的节点时,我们都会更新 ans

5. 调用 bfs 函数

  • solution 函数中,我们初始化 dp 数组,并调用 bfs 函数计算结果。
public static int solution(int row_n, int column_m, int[][] seats, int[] patient) {
    int[][] dp = new int[row_n+1][column_m+1];
    for(int i=0;i<row_n;i++){
        for(int j=0;j<column_m;j++){
            dp[i][j] = 1;
            if(seats[i][j] == 1) dp[i][j]++;
        }
    }
    int ans = bfs(patient[0],patient[1],row_n,column_m,dp);
    return ans;
}

6. 主函数测试

  • main 函数中,我们提供了几个测试用例来验证算法的正确性。
public static void main(String[] args) {
    int[][] testSeats1 = {{0,1,1,1},{1,0,1,0},{1,1,1,1},{0,0,0,1}};
    System.out.println(solution(4, 4, testSeats1, new int[]{2, 2}) == 6);
}

注意事项

  • 确保在 BFS 中正确处理戴口罩的人,他们需要更多的时间或被多个方向的人同时感染。
  • 在 BFS 中,如果一个座位上的人戴口罩,并且已经被感染,需要检查他们是否已经被周围的两个人感染,或者是否已经过了两秒钟。
  • 最终的结果应该是所有座位都被感染时的最大时间。