Minimum time required to rot all oranges | Dynamic Programming

Given a matrix of dimension m * n where each cell in the matrix can have values 0, 1 or 2 which has the following meaning:

0: Empty cell

1: Cells have fresh oranges

2: Cells have rotten oranges

So the task is to determine what is the minimum time required so that all the oranges become rotten. A rotten orange at index [i, j] can rot other fresh oranges at indexes [i – 1, j], [i + 1, j], [i, j – 1], [i, j + 1] (up, down, left and right). If it is impossible to rot every orange then simply return -1.

Examples:

Input: arr[][] = {
{2, 1, 0, 2, 1},
{1, 0, 1, 2, 1},
{1, 0, 0, 2, 1}};
Output: 2
In the first unit of time, all the oranges will be rotten
except the first orange of the last row
which will get rotten in the second unit of time.

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

Approach: A BFS based approach has been discussed here.

In this post we solve the problem using Dynamic Programming.

Every orange needs to be rotten. Any orange can be rotten by its nearest rotten orange. So, for every orange which is not rotten yet, we find its minimum distance from rotten orange, Then we take the maximum of all which will represent the minimum time required to rot all oranges.

Let dp(i, j) = Minimum Distance of this orange from any rotten orange So, the DP states will be:

dp(i, j) = 0 if arr[i][j] == 2
dp(i, j) = INT_MAX if arr[i][j] == 0
dp(i, j) = 1 + min(dp(i + 1, j), dp(i – 1, j), dp(i, j + 1), dp(i, j – 1))

And our answer will be max(dp(i, j)) for all i, j where arr[i][j] == 1

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <iostream>
using namespace std;
#define C 5
#define R 3
#define INT_MAX 10000000
  
// DP table to memoize the values
int table[R][C] = { 0 };
  
// Visited array to keep track of visited nodes
// in order to avoid infinite loops
int visited[R][C] = { 0 };
  
// Function to return the minimum of four numbers
int min(int p, int q, int r, int s)
{
    int temp1 = p < q ? p : q;
    int temp2 = r < s ? r : s;
  
    if (temp1 < temp2)
        return temp1;
    return temp2;
}
  
// Function to return the minimum distance
// to any rotten orange from [i, j]
int Distance(int arr[R][C], int i, int j)
{
    // If i, j  lie outside the array
    if (i >= R || j >= C || i < 0 || j < 0)
        return INT_MAX;
  
    // If result already exists in the table
    // use the memoized result
    else if (table[i][j] > 0 && table[i][j] < INT_MAX) {
        return table[i][j];
    }
  
    // If 0 then it can't lead to
    // any path so return INT_MAX
    else if (arr[i][j] == 0) {
        table[i][j] = INT_MAX;
        return INT_MAX;
    }
  
    // If 2 then we have reached our rotten oranges
    // so return from here
    else if (arr[i][j] == 2) {
        table[i][j] = 0;
        return 0;
    }
  
    // If this node is already visited
    // then return to avoid infinite loops
    else if (visited[i][j]) {
        return INT_MAX;
    }
    else {
  
        // Mark the current node as visited
        visited[i][j] = 1;
  
        // Check in all four possible directions
        int temp1 = Distance(arr, i + 1, j);
        int temp2 = Distance(arr, i - 1, j);
        int temp3 = Distance(arr, i, j + 1);
        int temp4 = Distance(arr, i, j - 1);
  
        // Take the minimum of all
        table[i][j] = 1 + min(temp1, temp2, temp3, temp4);
  
        visited[i][j] = 0;
    }
  
    return table[i][j];
}
  
// Function to return the minimum time
// required to rot all the oranges
int minTime(int arr[][C])
{
    int max = 0;
  
    // Calculate the minimum distances to any rotten
    // orange from all the fresh oranges
    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {
            if (arr[i][j] == 1)
                Distance(arr, i, j);
        }
    }
  
    // Pick the maximum distance of fresh orange
    // to some rotten orange
    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {
            if (arr[i][j] == 1 && table[i][j] > max)
                max = table[i][j];
        }
    }
  
    // If all oranges can be rotten
    if (max < INT_MAX)
        return max;
  
    return -1;
}
  
// Driver code
int main()
{
  
    int arr[R][C] = { { 2, 1, 0, 2, 1 },
                      { 0, 0, 1, 2, 1 },
                      { 1, 0, 0, 2, 1 } };
  
    cout << minTime(arr);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach
class GFG 
{
    static int C = 5;
    static int R = 3;
    static int INT_MAX = 10000000;
      
    // DP table to memoize the values
    static int [][]table = new int[R][C];
      
    // Visited array to keep track of visited nodes
    // in order to avoid infinite loops
    static int [][]visited = new int[R][C];
      
    // Function to return the minimum of four numbers
    static int min(int p, int q, int r, int s)
    {
        int temp1 = p < q ? p : q;
        int temp2 = r < s ? r : s;
      
        if (temp1 < temp2)
            return temp1;
        return temp2;
    }
      
    // Function to return the minimum distance
    // to any rotten orange from [i, j]
    static int Distance(int arr[][], int i, int j)
    {
        // If i, j lie outside the array
        if (i >= R || j >= C || i < 0 || j < 0)
            return INT_MAX;
      
        // If result already exists in the table
        // use the memoized result
        else if (table[i][j] > 0 &&
                 table[i][j] < INT_MAX) 
        {
            return table[i][j];
        }
      
        // If 0 then it can't lead to
        // any path so return INT_MAX
        else if (arr[i][j] == 0)
        {
            table[i][j] = INT_MAX;
            return INT_MAX;
        }
      
        // If 2 then we have reached our rotten oranges
        // so return from here
        else if (arr[i][j] == 2
        {
            table[i][j] = 0;
            return 0;
        }
      
        // If this node is already visited
        // then return to avoid infinite loops
        else if (visited[i][j] == 1
        {
            return INT_MAX;
        }
        else 
        {
      
            // Mark the current node as visited
            visited[i][j] = 1;
      
            // Check in all four possible directions
            int temp1 = Distance(arr, i + 1, j);
            int temp2 = Distance(arr, i - 1, j);
            int temp3 = Distance(arr, i, j + 1);
            int temp4 = Distance(arr, i, j - 1);
      
            // Take the minimum of all
            table[i][j] = 1 + min(temp1, temp2, 
                                  temp3, temp4);
      
            visited[i][j] = 0;
        }
        return table[i][j];
    }
      
    // Function to return the minimum time
    // required to rot all the oranges
    static int minTime(int arr[][])
    {
        int max = 0;
      
        // Calculate the minimum distances to any rotten
        // orange from all the fresh oranges
        for (int i = 0; i < R; i++) 
        {
            for (int j = 0; j < C; j++)
            {
                if (arr[i][j] == 1)
                    Distance(arr, i, j);
            }
        }
      
        // Pick the maximum distance of fresh orange
        // to some rotten orange
        for (int i = 0; i < R; i++)
        {
            for (int j = 0; j < C; j++) 
            {
                if (arr[i][j] == 1 &&
                    table[i][j] > max)
                    max = table[i][j];
            }
        }
      
        // If all oranges can be rotten
        if (max < INT_MAX)
            return max;
      
        return -1;
    }
      
    // Driver code
    public static void main(String[] args) 
    {
        int arr[][] = {{ 2, 1, 0, 2, 1 },
                       { 0, 0, 1, 2, 1 },
                       { 1, 0, 0, 2, 1 }};
      
        System.out.println(minTime(arr));
    }
}
  
// This code is contributed by Rajput-Ji

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python 3 implementation of the approach
C = 5
R = 3
INT_MAX = 10000000
  
# DP table to memoize the values
table = [[0 for i in range(C)] 
            for j in range(R)]
  
# Visited array to keep track of visited nodes
# in order to avoid infinite loops
visited = [[0 for i in range(C)] 
              for j in range(R)]
  
# Function to return the minimum of four numbers
def min(p, q, r, s):
    if(p < q):
        temp1 = p
    else:
        temp1 = q
    if(r < s):
        temp2 = r
    else:
        temp2 = s
      
    if (temp1 < temp2):
        return temp1
    return temp2
  
# Function to return the minimum distance
# to any rotten orange from [i, j]
def Distance(arr, i, j):
      
    # If i, j lie outside the array
    if (i >= R or j >= C or i < 0 or j < 0):
        return INT_MAX
  
    # If result already exists in the table
    # use the memoized result
    elif (table[i][j] > 0 and 
          table[i][j] < INT_MAX):
        return table[i][j]
  
    # If 0 then it can't lead to
    # any path so return INT_MAX
    elif (arr[i][j] == 0):
        table[i][j] = INT_MAX
        return INT_MAX
  
    # If 2 then we have reached 
    # our rotten oranges 
    # so return from here
    elif (arr[i][j] == 2):
        table[i][j] = 0
        return 0
  
    # If this node is already visited
    # then return to avoid infinite loops
    elif (visited[i][j]):
        return INT_MAX
    else:
        # Mark the current node as visited
        visited[i][j] = 1
  
        # Check in all four possible directions
        temp1 = Distance(arr, i + 1, j)
        temp2 = Distance(arr, i - 1, j)
        temp3 = Distance(arr, i, j + 1)
        temp4 = Distance(arr, i, j - 1)
  
        # Take the minimum of all
        table[i][j] = 1 + min(temp1, temp2,
                              temp3, temp4)
  
        visited[i][j] = 0
  
    return table[i][j]
  
# Function to return the minimum time
# required to rot all the oranges
def minTime(arr):
    max = 0
  
    # Calculate the minimum distances to any rotten
    # orange from all the fresh oranges
    for i in range(R):
        for j in range(C):
            if (arr[i][j] == 1):
                Distance(arr, i, j)
  
    # Pick the maximum distance of fresh orange
    # to some rotten orange
    for i in range(R):
        for j in range(C):
            if (arr[i][j] == 1 and 
                table[i][j] > max):
                max = table[i][j]
  
    # If all oranges can be rotten
    if (max < INT_MAX):
        return max
    return -1
  
# Driver code
if __name__ == '__main__':
    arr = [[2, 1, 0, 2, 1],
        [0, 0, 1, 2, 1],
        [1, 0, 0, 2, 1]]
  
    print(minTime(arr))
      
# This code is contributed by
# Surendra_Gangwar

chevron_right


C#

// C# implementation of the approach
using System;

class GFG
{
static int C = 5;
static int R = 3;
static int INT_MAX = 10000000;

// DP table to memoize the values
static int [,]table = new int[R, C];

// Visited array to keep track of visited nodes
// in order to avoid infinite loops
static int [,]visited = new int[R, C];

// Function to return the minimum of four numbers
static int min(int p, int q, int r, int s)
{
int temp1 = p < q ? p : q; int temp2 = r < s ? r : s; if (temp1 < temp2) return temp1; return temp2; } // Function to return the minimum distance // to any rotten orange from [i, j] static int Distance(int [,]arr, int i, int j) { // If i, j lie outside the array if (i >= R || j >= C || i < 0 || j < 0) return INT_MAX; // If result already exists in the table // use the memoized result else if (table[i, j] > 0 &&
table[i, j] < INT_MAX) { return table[i, j]; } // If 0 then it can't lead to // any path so return INT_MAX else if (arr[i, j] == 0) { table[i, j] = INT_MAX; return INT_MAX; } // If 2 then we have reached our rotten oranges // so return from here else if (arr[i, j] == 2) { table[i, j] = 0; return 0; } // If this node is already visited // then return to avoid infinite loops else if (visited[i, j] == 1) { return INT_MAX; } else { // Mark the current node as visited visited[i, j] = 1; // Check in all four possible directions int temp1 = Distance(arr, i + 1, j); int temp2 = Distance(arr, i - 1, j); int temp3 = Distance(arr, i, j + 1); int temp4 = Distance(arr, i, j - 1); // Take the minimum of all table[i, j] = 1 + min(temp1, temp2, temp3, temp4); visited[i, j] = 0; } return table[i, j]; } // Function to return the minimum time // required to rot all the oranges static int minTime(int [,]arr) { int max = 0; // Calculate the minimum distances to any rotten // orange from all the fresh oranges for (int i = 0; i < R; i++) { for (int j = 0; j < C; j++) { if (arr[i, j] == 1) Distance(arr, i, j); } } // Pick the maximum distance of fresh orange // to some rotten orange for (int i = 0; i < R; i++) { for (int j = 0; j < C; j++) { if (arr[i, j] == 1 && table[i, j] > max)
max = table[i, j];
}
}

// If all oranges can be rotten
if (max < INT_MAX) return max; return -1; } // Driver code public static void Main(String[] args) { int [,]arr = {{ 2, 1, 0, 2, 1 }, { 0, 0, 1, 2, 1 }, { 1, 0, 0, 2, 1 }}; Console.WriteLine(minTime(arr)); } } // This code is contributed by Rajput-Ji [tabbyending]

Output:

-1


My Personal Notes arrow_drop_up

Completely in love with Data Structure and Algorithms and GeeksForGeeks provides me with the opportunity to write my own articles, review and improve articles of others thereby strengthening my skills and it makes spreading and improving knowledge more fun than it earlier was

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.