Skip to content
Related Articles

Related Articles

Improve Article
Maximum time required for all patients to get infected
  • Difficulty Level : Hard
  • Last Updated : 28 Apr, 2021

Given a matrix arr[][], consisting of only 0, 1, and 2, that represents an empty ward, an uninfected patient, and an infected patient respectively. In one unit of time, an infected person at index (i, j) can infect an uninfected person adjacent to it i.e., at index (i – 1, j), (i + 1, j), (i, j – 1), and (i, j + 1). The task is to find the minimum amount of time required to infect all the patients. If it is impossible to infect all the patients, then print “-1”.

Examples:

Input: arr[][] = {{2, 1, 0, 2, 1}, {1, 0, 1, 2, 1}, {1, 0, 0, 2, 1}}
Output: 2
Explanation:
At time t = 1: The patients at positions {0, 0}, {0, 3}, {1, 3} and {2, 3} will infect patient at {{0, 1}, {1, 0}, {0, 4}, {1, 2}, {1, 4}, {2, 4}} during 1st unit time.
At time t = 2: The patient at {1, 0} will get infected and will infect patient at {2, 0}.

After the above time intervals all the uninfected patients are infected. Therefore, the total amount of time required is 2.

Input: arr[][] = {{2, 1, 0, 2, 1}, {0, 0, 1, 2, 1}, {1, 0, 0, 2, 1}}
Output: -1



Approach: The given problem can be solved by using BFS Traversal on the 2D matrix. Follow the steps below to solve the given problem:

  • Initialize a 2D array, say timeofinfection[][] with -1, such that timeofinfection[i][j] stores the time when the patient at index (i, j) was infected.
  • Initialize a queue to store indices of infected patients and their time of infection.
  • Traverse the given matrix arr[][] and perform the following operations:
    • If the value at cell (i, j) is 2, then push that cell into the queue with the time of infection as 0 i.e., {i, j, 0}.
    • Iterate until the queue is non-empty and perform the following steps:
      • Pop the front element of the queue and store it in a variable, say current.
      • From the current popped cell (i, j), if the adjacent cell has an infected person which is unvisited, then push the index of the adjacent cell with (1 + time of infection of the current popped cell) into the queue.
  • After completing the above steps, if all the infected persons are visited, i.e. the time of infection of all the infected persons is non-negative, then print the maximum element present in the matrix timeofinfection[][] as the maximum unit of time required to infect all the patients.
  • Otherwise, print “-1”.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Direction arrays
vector<pair<int, int> > direction
    = { { 1, 0 }, { 0, -1 }, { -1, 0 }, { 0, 1 } };
 
// Function to find the maximum time
// required for all patients to get infected
int maximumTime(vector<vector<int> > arr)
{
    // Stores the number of rows
    int n = arr.size();
 
    // Stores the number of columns
    int m = arr[0].size();
 
    // Stores the time of infection
    // of the patient at index (i, j)
    int timeofinfection[n][m];
 
    // Stores index and time of
    // infection of infected persions
    queue<pair<pair<int, int>, int> > q;
 
    // Traverse the matrix
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
 
            // Set the cell as unvisited
            timeofinfection[i][j] = -1;
 
            // If the current patient
            // is already infected
            if (arr[i][j] == 2) {
 
                // Push the index and time of
                // infection of current patient
                q.push({ { i, j }, 0 });
                timeofinfection[i][j] = 0;
            }
        }
    }
 
    // Iterate until queue becomes empty
    while (!q.empty()) {
        // Stores the front element of queue
        pair<pair<int, int>, int> current
            = q.front();
 
        // Pop out the front element
        q.pop();
 
        // Check for all four
        // adjacent indices
        for (auto it : direction) {
 
            // Find the index of the
            // adjacent cell
            int i = current.first.first
                    + it.first;
            int j = current.first.second
                    + it.second;
 
            // If the current adjacent
            // cell is invalid or it
            // contains an infected patient
            if (i < 0 || j < 0 || i >= n
                || j >= m || arr[i][j] != 1
                || timeofinfection[i][j] != -1) {
 
                // Continue to the next
                // neighbouring cell
                continue;
            }
 
            // Push the infected
            // neighbour into queue
            q.push({ { i, j },
                     current.second + 1 });
            timeofinfection[i][j]
                = current.second + 1;
        }
    }
 
    // Stores the maximum time
    int maxi = INT_MIN;
 
    // Stores if any uninfected
    // patient exists or not
    int flag = 0;
 
    // Traverse the matrix
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            // If no patient is
            // present at index (i, j)
            if (arr[i][j] != 1)
                continue;
 
            // If an uninfected patient
            // is present at index (i, j)
            if (arr[i][j] == 1
                && timeofinfection[i][j] == -1) {
                // Set flag as true
                flag = 1;
                break;
            }
 
            // Update the maximum time of infection
            maxi = max(maxi, timeofinfection[i][j]);
        }
    }
 
    // If an ininfected patient is present
    if (flag)
        return -1;
 
    // Return the final result
    return maxi;
}
 
// Driver Code
int main()
{
    vector<vector<int> > arr
        = { { 2, 1, 0, 2, 1 },
            { 1, 0, 1, 2, 1 },
            { 1, 0, 0, 2, 1 } };
    cout << maximumTime(arr);
 
    return 0;
}

Java




// Java program for the above approach
import java.util.*;
 
class GFG {
     
static class pair
{
    int first, second, third;
     
    pair(int first,int second,int third)
    {
         this.first = first;
         this.second = second;
         this.third = third;
    }
}   
     
// Direction arrays
static int[][] direction = { { 1, 0 }, { 0, -1 },
                             { -1, 0 }, { 0, 1 } };
 
// Function to find the maximum time
// required for all patients to get infected
static int maximumTime(int[][] arr)
{
     
    // Stores the number of rows
    int n = arr.length;
 
    // Stores the number of columns
    int m = arr[0].length;
 
    // Stores the time of infection
    // of the patient at index (i, j)
    int[][] timeofinfection = new int[n][m];
 
    // Stores index and time of
    // infection of infected persions
    Queue<pair> q = new LinkedList<>();
 
    // Traverse the matrix
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
 
            // Set the cell as unvisited
            timeofinfection[i][j] = -1;
 
            // If the current patient
            // is already infected
            if (arr[i][j] == 2)
            {
                 
                // Push the index and time of
                // infection of current patient
                q.add(new pair(i, j, 0));
                timeofinfection[i][j] = 0;
            }
        }
    }
 
    // Iterate until queue becomes empty
    while (!q.isEmpty())
    {
         
        // Stores the front element of queue
        pair current = q.peek();
 
        // Pop out the front element
        q.poll();
 
        // Check for all four
        // adjacent indices
        for(int[] it : direction)
        {
             
            // Find the index of the
            // adjacent cell
            int i = current.first + it[0];
            int j = current.second + it[1];
 
            // If the current adjacent
            // cell is invalid or it
            // contains an infected patient
            if (i < 0 || j < 0 || i >= n ||
               j >= m || arr[i][j] != 1 ||
               timeofinfection[i][j] != -1)
            {
 
                // Continue to the next
                // neighbouring cell
                continue;
            }
 
            // Push the infected
            // neighbour into queue
            q.add(new pair(i, j ,
                           current.second + 1 ));
            timeofinfection[i][j] = current.third + 1;
        }
    }
 
    // Stores the maximum time
    int maxi = Integer.MIN_VALUE;
 
    // Stores if any uninfected
    // patient exists or not
    int flag = 0;
 
    // Traverse the matrix
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
             
            // If no patient is
            // present at index (i, j)
            if (arr[i][j] != 1)
                continue;
 
            // If an uninfected patient
            // is present at index (i, j)
            if (arr[i][j] == 1 && timeofinfection[i][j] == -1)
            {
                 
                // Set flag as true
                flag = 1;
                break;
            }
 
            // Update the maximum time of infection
            maxi = Math.max(maxi, timeofinfection[i][j]);
        }
    }
 
    // If an ininfected patient is present
    if (flag == 1)
        return -1;
 
    // Return the final result
    return maxi;
}
 
// Driver code
public static void main(String[] args)
{
    int[][] arr = { { 2, 1, 0, 2, 1 },
                    { 1, 0, 1, 2, 1 },
                    { 1, 0, 0, 2, 1 } };
    System.out.print(maximumTime(arr));
}
}
 
// This code is contributed by offbeat
Output
2

Time Complexity: O(N * M)
Auxiliary Space: O(N * M)

Approach 2:This uses the same  BFS traversal technique but instead of using an array of integer to keep track of whether all patients are infected it uses a single integer which reduces overall space consumption and overhead of doing an extra check for uninfected patients.

The basic idea is we will store the count of uninfected persons at the start and as an individual will got infected we will decrement this count. This will remove the overhead of checking  for uninfected persons at the end. And the time at which the last person got  infected will be our final answer.  

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Direction arrays
vector<pair<int, int> > direction
    = { { 1, 0 }, { 0, -1 }, { -1, 0 }, { 0, 1 } };
 
// Function to find the maximum time
// required for all patients to get infected
int maximumTime(vector<vector<int> > arr)
{
    // Stores the number of rows
    int n = arr.size();
 
    // Stores the number of columns
    int m = arr[0].size();
 
    // Stores wether particular index(i, j)
    // is visited or not 
    vector<vector<bool>> visited(n,vector<bool>(m,0));
 
    // Stores index and time of
    // infection of infected persions
    queue<pair<pair<int, int>, int> > q;
   
    //Stores uninfected patients count 
      int uninfected_count=0;
     
      //Stores time at which last person got infected
      int time = 0;
    // Traverse the matrix
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
 
            // If the current patient
            // is already infected
            if (arr[i][j] == 2) {
 
                // Push the index of current patient
                // and mark it as visited
                q.push({ { i, j }, 0 });
                visited[i][j] =  1;
            }
           
            //If current patient is uninfected
              //increment uninfected count
              if(arr[i][j] == 1){
                uninfected_count++;
            }
        }
    }
 
    // Iterate until queue becomes empty
    while (!q.empty()) {
        // Stores the front element of queue
        pair<pair<int, int>, int> current
            = q.front();
           
        time = current.second;
        // Pop out the front element
        q.pop();
 
        // Check for all four
        // adjacent indices
        for (auto it : direction) {
 
            // Find the index of the
            // adjacent cell
            int i = current.first.first
                    + it.first;
            int j = current.first.second
                    + it.second;
 
            // If the current adjacent
            // cell is invalid or it
            // contains an infected patient
            if (i < 0 || j < 0 || i >= n
                || j >= m || arr[i][j] != 1
                || visited[i][j] != 0) {
 
                // Continue to the next
                // neighbouring cell
                continue;
            }
 
            // Push the infected
            // neighbour into queue
            q.push({ { i, j }, time + 1 });
            visited[i][j] = 1;
              uninfected_count--;
        }
    }
 
    // If an uninfected patient is present
    if (uninfected_count != 0)
        return -1;
 
      // Return the final result
    return time;
}
 
// Driver Code
int main()
{
    vector<vector<int> > arr
        = { { 2, 1, 0, 2, 1 },
            { 1, 0, 1, 2, 1 },
            { 1, 0, 0, 2, 1 } };
    cout << maximumTime(arr);
 
    return 0;
}
// Contributed By Devendra Kolhe

Java




// Java program for the above approach
import java.util.*;
 
public class GFG{
     
    static class pair
    {
        int first, second, third;
          
        pair(int first,int second,int third)
        {
             this.first = first;
             this.second = second;
             this.third = third;
        }
    }
     
    // Direction arrays
    static int direction[][] = { { 1, 0 }, { 0, -1 },
                            { -1, 0 }, { 0, 1 } };
     
    // Function to find the maximum time
    // required for all patients to get infected
    static int maximumTime(int arr[][])
    {
        // Stores the number of rows
        int n = arr.length;
     
        // Stores the number of columns
        int m = arr[0].length;
     
        // Stores wether particular index(i, j)
        // is visited or not
        boolean visited[][] = new boolean[n][m];
     
        // Stores index and time of
        // infection of infected persions
        Queue<pair> q = new LinkedList<>();
     
        //Stores uninfected patients count
        int uninfected_count=0;
         
        //Stores time at which last person got infected
        int time = 0;
        // Traverse the matrix
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
     
                // If the current patient
                // is already infected
                if (arr[i][j] == 2) {
     
                    // Push the index of current patient
                    // and mark it as visited
                    q.add( new pair(i, j, 0 ));
                    visited[i][j] = true;
                }
             
                //If current patient is uninfected
                //increment uninfected count
                if(arr[i][j] == 1){
                    uninfected_count++;
                }
            }
        }
     
        // Iterate until queue becomes empty
        while (!q.isEmpty()) {
            // Stores the front element of queue
            pair current = q.peek();
             
            time = current.third;
            // Pop out the front element
            q.poll();
     
            // Check for all four
            // adjacent indices
            for (int[] it : direction) {
     
                // Find the index of the
                // adjacent cell
                int i = current.first
                        + it[0];
                int j = current.second
                        + it[1];
     
                // If the current adjacent
                // cell is invalid or it
                // contains an infected patient
                if (i < 0 || j < 0 || i >= n
                    || j >= m || arr[i][j] != 1
                    || visited[i][j]) {
     
                    // Continue to the next
                    // neighbouring cell
                    continue;
                }
     
                // Push the infected
                // neighbour into queue
                q.add( new pair( i, j, time + 1 ));
                visited[i][j] = true;
                uninfected_count--;
            }
        }
     
        // If an uninfected patient is present
        if (uninfected_count != 0)
            return -1;
     
        // Return the final result
        return time;
    }
     
    // Driver Code
    public static void main(String args[])
    {
        int arr[][] = { { 2, 1, 0, 2, 1 },
                    { 1, 0, 1, 2, 1 },
                    { 1, 0, 0, 2, 1 } };
                     
        System.out.println(maximumTime(arr));
     
    }
}
 
// This code is contributed by adityapande88.
Output
2

   

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with industry experts, please refer Geeks Classes Live 




My Personal Notes arrow_drop_up
Recommended Articles
Page :