Saturday, September 21, 2024
Google search engine
HomeLanguagesDynamic ProgrammingMinimum total power consumption by both the current “+” & “-“

Minimum total power consumption by both the current “+” & “-“

Given a matrix of size rows x cols called “power,” which represents the power associated with each cell in the field. There are two types of current flow in the field: “+” current starts from the top left corner, while “-” current starts from the top right corner. Both types of current can move in three directions: from a cell (i, j) to either (i + 1, j – 1), (i + 1, j), or (i + 1, j + 1). The power consumption between two cells is calculated as the absolute difference between the power values of the two cells: abs(power[i + 1][j + 1] – power[i][j]). The task is to calculate the minimum total power consumption by both the current “+” & “-” to reach the last row.

Note:   At any given point (i, j), both types of current cannot occupy the same cell simultaneously, as it would cause an electric shock.

Examples: 

Input: power[][] = {{2, 4}, {3, 9}}
Output: combined minimum power : 6
Explanation: The “+” current chooses the path 2 -> 3, and the “-” current chooses the path 4 -> 9. The minimum total power consumption [abs(3 – 2) + abs(9 – 4)] = 1 + 5 = 6

Input: power[][] = {{2, 4, 6}, {8, 0, 10}, {6, 3, 9}}
Output: combined minimum power : 10
Explanation:  The “+” current chooses the path 2 -> 0-> 3, and the “-” current chooses the path 6->10-> 9. The minimum total power consumption [abs(0 – 2) + abs(3 – 0) + abs(10 – 6) + abs(9 – 10)] = 5 + 5= 10.

Approach: To solve the problem using Recursion follow the below idea:

  • As mentioned in the question, both “+” and “-” currents can move in three directions: (i + 1, j – 1), (i + 1, j), or (i + 1, j + 1). Therefore, the total combined directions will be 3 * 3 = 9. For each “+” current, there will be three possible ways for the “-” current to move. We need to consider all the possible 9 directions.
  • The base case occurs when both the “+” and “-” currents reach the last row, which will be the minimum valid position. Once they reach the last row, it becomes the base case.
  • Now, for all possible paths, we calculate the minimum and return it as the result.

Mathematically the recursion will look like the following:

  • value = abs(power[next_i][next_j1] – power[i][j1]) + abs(power[next_i][next_J2] – power[i][j2]);
  • value += totalPower(next_i, next_j1, next_j2, power, rows, cols);
  • mini = min(mini, value);
  • // base case { once it reaches to last row. }
    • i == power.size()-1;

Steps to solve the problem:

  • Build a recursive function and pass the starting row, col for both the current.
  • For each (i, j) check if it’s valid or not, if it’s valid store the power consumption and call recursion for next.
  • compare all the paths and take out the minimum power consumption.

Below is the implementation for the above approach:

C++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
int totalPower(int i, int j1, int j2, int power[][3],
               int rows, int cols)
{
 
    // Base case: both "+" and "-"
    // reach the last row
    if (i == rows - 1)
        return 0;
 
    int mini = INT_MAX;
 
    // At each (i, j), there are 9
    // combined possibilities 3 possibilities
    // for j1 (from -1 to 1), and the same
    // for j2 Thus, a total of 3 * 3
    // possibilities
    for (int k = -1; k <= 1; k++) {
        for (int p = -1; p <= 1; p++) {
            int nextI = i + 1;
            int nextJ1 = j1 + k;
            int nextJ2 = j2 + p;
 
            // Check the validity of the
            // path and ensure there
            // is no collision
            if (nextI >= 0 && nextI < rows && nextJ1 >= 0
                && nextJ1 < cols && nextJ2 >= 0
                && nextJ2 < cols && nextJ1 != nextJ2) {
                int value = abs(power[nextI][nextJ1]
                                - power[i][j1])
                            + abs(power[nextI][nextJ2]
                                  - power[i][j2]);
 
                // Recursively call for
                // the next i, j1, and j2
                value += totalPower(nextI, nextJ1, nextJ2,
                                    power, rows, cols);
 
                // Take the minimum
                mini = min(mini, value);
            }
        }
    }
 
    // return the answer
    return mini;
}
 
// Driver code
int main()
{
    int power[][3]
        = { { 2, 4, 6 }, { 8, 0, 10 }, { 6, 3, 9 } };
    int rows = sizeof(power) / sizeof(power[0]);
    int cols = sizeof(power[0]) / sizeof(power[0][0]);
 
    // Function call
    cout << "Combined Minimum Power: "
         << totalPower(0, 0, cols - 1, power, rows, cols)
         << endl;
    return 0;
}


Java




// Java code for the above approach
import java.util.*;
 
class GFG {
    static int totalPower(int i, int j1, int j2,
                          int power[][], int rows, int cols)
    {
 
        // Base case: both "+" and "-"
        // reach the last row
        if (i == rows - 1)
            return 0;
 
        int mini = Integer.MAX_VALUE;
 
        // At each (i, j), there are 9
        // combined possibilities 3 possibilities
        // for j1 (from -1 to 1), and the same
        // for j2 Thus, a total of 3 * 3
        // possibilities
        for (int k = -1; k <= 1; k++) {
            for (int p = -1; p <= 1; p++) {
                int nextI = i + 1;
                int nextJ1 = j1 + k;
                int nextJ2 = j2 + p;
 
                // Check the validity of the
                // path and ensure there
                // is no collision
                if (nextI >= 0 && nextI < rows
                    && nextJ1 >= 0 && nextJ1 < cols
                    && nextJ2 >= 0 && nextJ2 < cols
                    && nextJ1 != nextJ2) {
                    int value
                        = Math.abs(power[nextI][nextJ1]
                                   - power[i][j1])
                          + Math.abs(power[nextI][nextJ2]
                                     - power[i][j2]);
 
                    // Recursively call for
                    // the next i, j1, and j2
                    value
                        += totalPower(nextI, nextJ1, nextJ2,
                                      power, rows, cols);
 
                    // Take the minimum
                    mini = Math.min(mini, value);
                }
            }
        }
 
        // return the answer
        return mini;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int power[][]
            = { { 2, 4, 6 }, { 8, 0, 10 }, { 6, 3, 9 } };
        int rows = power.length;
        int cols = power[0].length;
 
        // Function call
        System.out.println("Combined Minimum Power: "
                           + totalPower(0, 0, cols - 1,
                                        power, rows, cols));
    }
}
 
// This code is contributed by Tapesh(tapeshdua420)


Python3




def totalPower(i, j1, j2, power, rows, cols):
    # Base case: both "+" and "-" reach the last row
    if i == rows - 1:
        return 0
 
    mini = float('inf')
 
    # At each (i, j), there are 9 combined possibilities
    # 3 possibilities for j1 (from -1 to 1), and the same for j2
    # Thus, a total of 3 * 3 possibilities
    for k in range(-1, 2):
        for p in range(-1, 2):
            nextI = i + 1
            nextJ1 = j1 + k
            nextJ2 = j2 + p
 
            # Check the validity of the path and ensure there is no collision
            if (
                0 <= nextI < rows
                and 0 <= nextJ1 < cols
                and 0 <= nextJ2 < cols
                and nextJ1 != nextJ2
            ):
                value = (
                    abs(power[nextI][nextJ1] - power[i][j1])
                    + abs(power[nextI][nextJ2] - power[i][j2])
                )
 
                # Recursively call for the next i, j1, and j2
                value += totalPower(nextI, nextJ1, nextJ2, power, rows, cols)
 
                # Take the minimum
                mini = min(mini, value)
 
    # return the answer
    return mini
 
# Driver code
if __name__ == "__main__":
    power = [[2, 4, 6], [8, 0, 10], [6, 3, 9]]
    rows = len(power)
    cols = len(power[0])
 
    # Function call
    print("Combined Minimum Power:", totalPower(0, 0, cols - 1, power, rows, cols))
#This code is Contributed by chinmaya121221


Output

Combined Minimum Power: 10






Complexity Analysis: 

  • Time Complexity: O(3n + 3n) The above solution may try all the possiable path in worst case. Therefore time complexity of the above solution is exponential.
  • Auxiliary Space: O(n) where n is recursion stack space.

Using Memoization :

Each state of the solution can be uniquely identified using three variables – rows,col1 & col2 (for both “+” and “-“) . So create a 3D array to store the value of each state to avoid recalculation of the same state.

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
int columns = 0;
int totalPower(int i, int j1, int j2, int power[][3], int rows, int cols, int memo[][3][3]) {
    // Base case: both "+" and "-" reach the last row
    if (i == rows - 1)
        return 0;
     
    // Check if the value is already calculated and stored in memo
    if (memo[i][j1][j2] != -1)
        return memo[i][j1][j2];
     
    int mini = INT_MAX;
     
    // At each (i, j), there are 9 combined possibilities
    // 3 possibilities for j1 (from -1 to 1), and the same for j2
    // Thus, a total of 3 * 3 possibilities
    for (int k = -1; k <= 1; k++) {
        for (int p = -1; p <= 1; p++) {
            int nextI = i + 1;
            int nextJ1 = j1 + k;
            int nextJ2 = j2 + p;
 
            // Check the validity of the path and ensure there is no collision
            if (nextI >= 0 && nextI < rows && nextJ1 >= 0 && nextJ1 < cols && nextJ2 >= 0 && nextJ2 < cols && nextJ1 != nextJ2) {
                int value = abs(power[nextI][nextJ1] - power[i][j1]) + abs(power[nextI][nextJ2] - power[i][j2]);
                // Recursively call for the next i, j1, and j2
                value += totalPower(nextI, nextJ1, nextJ2, power, rows, cols, memo);
                // Take the minimum
                mini = min(mini, value);
            }
        }
    }
     
    // Store the calculated value in memo
    memo[i][j1][j2] = mini;
     
    // Return the answer
    return mini;
}
 
// Driver code
int main() {
    int power[][3] = {{2, 4, 6}, {8, 0, 10}, {6, 3, 9}};
    int rows = sizeof(power) / sizeof(power[0]);
    int cols = sizeof(power[0]) / sizeof(power[0][0]);
    columns = cols;
    int memo[rows][3][3];
    memset(memo, -1, sizeof(memo)); // Initialize memo with -1
     
    cout << "Combined Minimum Power: " << totalPower(0, 0, cols - 1, power, rows, cols, memo) << endl;
    return 0;
}


Output

Combined Minimum Power: 10






Complexity Analysis: 

  • Time Complexity: The time complexity of the given solution is O(N3), where N represents the number of columns in the power matrix. This is because, at each cell (i, j1, j2), we iterate over all possible combinations of j1 and j2.
  • Auxiliary Space: The space complexity of the given solution is O(N3) as well. This is because we use a 3D array memo to store the calculated values for each state (i, j1, j2), resulting in a space requirement of O(N3).
Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

RELATED ARTICLES

Most Popular

Recent Comments