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:
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 

if dp(i, j) >0 and dp(i, j)<INT_MAX 
then dp(i, j) = min(dp(i, j) , 1 + min(dp(i + 1, j), 
                                  dp(i – 1, j), dp(i, j + 1), dp(i, j – 1)))

else 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 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
        int min_value = 1 + min(temp1,
                    temp2, temp3, temp4);
 
        // If result already exists in the table
        // check if min_value is less
        // than existing value
        if (table[i][j] > 0 &&
            table[i][j] < INT_MAX) {
            if (min_value < table[i][j])
                table[i][j] = min_value;
        }
        else
            table[i][j] = min_value;
        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 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
            int min_value
                = 1 + min(temp1, temp2, temp3, temp4);
            // If result already exists in
            // the table check if min_value
            // is less than existing value
            if (table[i][j] > 0 &&
                table[i][j] < INT_MAX) {
                if (min_value < table[i][j])
                    table[i][j] = min_value;
            }
            else
                table[i][j] = min_value;
 
            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 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
        min_value = 1 + min(temp1, temp2,
                            temp3, temp4)
 
        if table[i][j] > 0 and \
                table[i][j] < INT_MAX:
            if min_value < table[i][j]:
                table[i][j] = min_value
        else:
            table[i][j] = min_value
 
        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))

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation of
// the above 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 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
    int min_value = 1 + min(temp1, temp2,
                            temp3, temp4);
    // If result already exists in
    // the table check if min_value
    // is less than existing value
    if (table[i, j] > 0 &&
        table[i, j] < INT_MAX)
    {
      if (min_value < table[i, j])
        table[i, j] = min_value;
    }
    else
      table[i, j] = min_value;
 
    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.Write(minTime(arr));
}
}
 
// This code is contributed by Chitranayal

chevron_right


Output

-1

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.




My Personal Notes arrow_drop_up

I like solving algorithmic problems 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.