Open In App

Number of Ways to Cut a Rectangular Pie such that each piece contains at least one Orange

Last Updated : 16 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

You are given a Rectangular Pie, represented as a 2D matrix containing the following characters: ‘O‘ (an orange) and ‘ . ‘ (empty cell). You have given an integer P to cut the pie into P pieces using P-1 cuts. For each cut you choose the direction vertical or horizontal, then you choose a cut position at the cell boundary and cut the pie into two pieces. If you cut the pie vertically, give the left part of the pie to a person. if you cut the pie horizontally, give the upper part of the pie to a person. In the end, give the last piece of pie to the last person.

Your task is to print the number of ways to cut the pie such that each piece contains at least one Orange. Since the answer can be a huge number, return this modulo 109+7.

Examples:

Input: pie = [“O . .”, “O O O”,”. . .”] , P=3
Output : 3
Number-of-ways-to-cut-a-pie
Explanation : There are 3 different ways of cutting the pie such that each piece of pie has at least one piece of orange, Shown in image above.

Input : pie = [“O . . “, “O . .”, “. . .”] , P=1
Output : 1
Explanation : Taking the whole pie will give us 1 piece n total.

Number of Ways to Cut a Rectangular Pie Using Dynamic Programming:

  • We can solve this problem using dynamic programming where each state can be defined by row , column represents the upper left coordinates of pie and number of cuts left.
  • We apply a cut if cell is valid and call the recursive function. if any state is already calculated return its value otherwise calculate number of ways to apply remaining cuts in the pie and store its value in the dp array.
  • Base Cases: If cuts_left is 0, return 1 (one valid way to finish).
  • isValid Function: Implement a function isValid that checks whether there is at least one orange in a given sub-matrix.
  • Main Function ways:
    • Implement a function ways that takes pie (the input grid) and P (the number of pieces to be cut).
    • If P is 1, check if the whole pie is valid and return 1 if true, 0 otherwise.
    • Initialize the DP array dp with -1 and call the recursive function.

Below is the implementation of above approach:

C++14




#include <bits/stdc++.h>
using namespace std;
 
long long MOD = 1000000007;
long long dp[51][51]
            [11]; // 3D array for dynamic programming
 
// Function to check if there's at least one 'O' in a given
// sub-matrix.
bool isValid(vector<string>& pie, int startRow, int endRow,
             int startCol, int endCol)
{
    for (int i = startRow; i <= endRow; i++) {
        for (int j = startCol; j <= endCol; j++) {
            // if there is a pie then return true
            if (pie[i][j] == 'O') {
                return true;
            }
        }
    }
    // No pie found
    return false;
}
 
// Recursive solver function for dynamic programming.
int solver(vector<string>& pie, int startRow, int startCol,
           int cutsleft)
{
    int m = pie.size(), n = pie[0].size();
 
    // Base case: No cuts left, return 1 (one valid way to
    // finish)
    if (cutsleft == 0)
        return 1;
 
    // If this state has been computed before, return the
    // stored value.
    if (dp[startRow][startCol][cutsleft] != -1)
        return dp[startRow][startCol][cutsleft];
 
    long long ans = 0;
 
    // Loop for vertical cuts
    for (int row = startRow; row < m - 1; row++) {
        bool upperhalfvalid
            = isValid(pie, startRow, row, startCol, n - 1);
        bool lowerhalfvalid
            = isValid(pie, row + 1, m - 1, startCol, n - 1);
 
        if (upperhalfvalid and lowerhalfvalid) {
            int nextways = solver(pie, row + 1, startCol,
                                  cutsleft - 1);
            ans = (ans + nextways) % MOD;
        }
    }
 
    // Loop for horizontal cuts
    for (int col = startCol; col < n - 1; col++) {
        bool lefthalfvalid
            = isValid(pie, startRow, m - 1, startCol, col);
        bool righthalfvalid
            = isValid(pie, startRow, m - 1, col + 1, n - 1);
 
        if (lefthalfvalid and righthalfvalid) {
            int nextways = solver(pie, startRow, col + 1,
                                  cutsleft - 1);
            ans = (ans + nextways) % MOD;
        }
    }
 
    // Store the computed result and return
    return dp[startRow][startCol][cutsleft] = ans;
}
 
// Main function to calculate ways to cut the pie.
int ways(vector<string>& pie, int P)
{
    int m = pie.size(), n = pie[0].size();
 
    // If P is 1, check if the whole pie is valid and return
    // 1 if true, 0 otherwise.
    if (P == 1)
        return (isValid(pie, 0, m - 1, 0, n - 1) ? 1 : 0);
 
    // Initialize DP array with -1 and call the solver
    // function.
    memset(dp, -1, sizeof(dp));
    int ans = solver(pie, 0, 0, P - 1);
    return ans;
}
 
int main()
{
    vector<string> pie = { "O..", "OOO", "..." };
    int P = 3;
    cout << ways(pie, P); // Print the result
}


Java




import java.util.Arrays;
import java.util.Vector;
 
public class PieCutting {
 
    static long MOD = 1000000007;
    static long[][][] dp; // 3D array for dynamic programming
 
    // Function to check if there's at least one 'O' in a given sub-matrix.
    static boolean isValid(Vector<String> pie, int startRow, int endRow, int startCol, int endCol) {
        for (int i = startRow; i <= endRow; i++) {
            for (int j = startCol; j <= endCol; j++) {
                // if there is a pie then return true
                if (pie.get(i).charAt(j) == 'O') {
                    return true;
                }
            }
        }
        // No pie found
        return false;
    }
 
    // Recursive solver function for dynamic programming.
    static int solver(Vector<String> pie, int startRow, int startCol, int cutsLeft) {
        int m = pie.size(), n = pie.get(0).length();
 
        // Base case: No cuts left, return 1 (one valid way to finish)
        if (cutsLeft == 0)
            return 1;
 
        // If this state has been computed before, return the stored value.
        if (dp[startRow][startCol][cutsLeft] != -1)
            return (int) dp[startRow][startCol][cutsLeft];
 
        long ans = 0;
 
        // Loop for vertical cuts
        for (int row = startRow; row < m - 1; row++) {
            boolean upperHalfValid = isValid(pie, startRow, row, startCol, n - 1);
            boolean lowerHalfValid = isValid(pie, row + 1, m - 1, startCol, n - 1);
 
            if (upperHalfValid && lowerHalfValid) {
                int nextWays = solver(pie, row + 1, startCol, cutsLeft - 1);
                ans = (ans + nextWays) % MOD;
            }
        }
 
        // Loop for horizontal cuts
        for (int col = startCol; col < n - 1; col++) {
            boolean leftHalfValid = isValid(pie, startRow, m - 1, startCol, col);
            boolean rightHalfValid = isValid(pie, startRow, m - 1, col + 1, n - 1);
 
            if (leftHalfValid && rightHalfValid) {
                int nextWays = solver(pie, startRow, col + 1, cutsLeft - 1);
                ans = (ans + nextWays) % MOD;
            }
        }
 
        // Store the computed result and return
        return (int) (dp[startRow][startCol][cutsLeft] = ans);
    }
 
    // Main function to calculate ways to cut the pie.
    static int ways(Vector<String> pie, int P) {
        int m = pie.size(), n = pie.get(0).length();
 
        // If P is 1, check if the whole pie is valid and return 1 if true, 0 otherwise.
        if (P == 1)
            return (isValid(pie, 0, m - 1, 0, n - 1) ? 1 : 0);
 
        // Initialize DP array with -1 and call the solver function.
        dp = new long[m][n][P];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                Arrays.fill(dp[i][j], -1);
            }
        }
 
        int ans = solver(pie, 0, 0, P - 1);
        return ans;
    }
 
    public static void main(String[] args) {
        Vector<String> pie = new Vector<>();
        pie.add("O..");
        pie.add("OOO");
        pie.add("...");
 
        int P = 3;
        System.out.println(ways(pie, P)); // Print the result
    }
}
 
// This code is contributed by shivamgupta310570


Python3




MOD = 1000000007
 
# 3D array for dynamic programming
dp = [[[None for _ in range(11)] for _ in range(51)] for _ in range(51)]
 
 
# Function to check if there's at least one 'O' in a given sub-matrix.
def is_valid(pie, start_row, end_row, start_col, end_col):
    for i in range(start_row, end_row + 1):
        for j in range(start_col, end_col + 1):
            # if there is a pie then return true
            if pie[i][j] == 'O':
                return True
    # No pie found
    return False
 
 
# Recursive solver function for dynamic programming.
def solver(pie, start_row, start_col, cuts_left):
    m, n = len(pie), len(pie[0])
 
    # Base case: No cuts left, return 1 (one valid way to finish)
    if cuts_left == 0:
        return 1
 
    # If this state has been computed before, return the stored value.
    if dp[start_row][start_col][cuts_left] is not None:
        return dp[start_row][start_col][cuts_left]
 
    ans = 0
 
    # Loop for vertical cuts
    for row in range(start_row, m - 1):
        upper_half_valid = is_valid(pie, start_row, row, start_col, n - 1)
        lower_half_valid = is_valid(pie, row + 1, m - 1, start_col, n - 1)
 
        if upper_half_valid and lower_half_valid:
            next_ways = solver(pie, row + 1, start_col, cuts_left - 1)
            ans = (ans + next_ways) % MOD
 
    # Loop for horizontal cuts
    for col in range(start_col, n - 1):
        left_half_valid = is_valid(pie, start_row, m - 1, start_col, col)
        right_half_valid = is_valid(pie, start_row, m - 1, col + 1, n - 1)
 
        if left_half_valid and right_half_valid:
            next_ways = solver(pie, start_row, col + 1, cuts_left - 1)
            ans = (ans + next_ways) % MOD
 
    # Store the computed result and return
    dp[start_row][start_col][cuts_left] = ans
    return ans
 
 
# Main function to calculate ways to cut the pie.
def ways(pie, P):
    m, n = len(pie), len(pie[0])
 
    # If P is 1, check if the whole pie is valid and return 1 if true, 0 otherwise.
    if P == 1:
        return 1 if is_valid(pie, 0, m - 1, 0, n - 1) else 0
 
    # Initialize DP array with None and call the solver function.
    for i in range(51):
        for j in range(51):
            for k in range(11):
                dp[i][j][k] = None
 
    ans = solver(pie, 0, 0, P - 1)
    return ans
 
# Driver code
if __name__ == "__main__":
    pie = ["O..", "OOO", "..."]
    P = 3
    print(ways(pie, P))  # Print the result


C#




using System;
 
class Program
{
    static long MOD = 1000000007;
    static long[,,] dp;
 
    // Function to check if there's at least one 'O' in a given sub-matrix.
    static bool IsValid(string[] pie, int startRow, int endRow, int startCol, int endCol)
    {
        for (int i = startRow; i <= endRow; i++)
        {
            for (int j = startCol; j <= endCol; j++)
            {
                // If there is a 'O' then return true
                if (pie[i][j] == 'O')
                {
                    return true;
                }
            }
        }
        // No 'O' found
        return false;
    }
 
    // Recursive solver function for dynamic programming.
    static int Solver(string[] pie, int startRow, int startCol, int cutsLeft)
    {
        int m = pie.Length, n = pie[0].Length;
 
        // Base case: No cuts left, return 1 (one valid way to finish)
        if (cutsLeft == 0)
            return 1;
 
        // If this state has been computed before, return the stored value.
        if (dp[startRow, startCol, cutsLeft] != -1)
            return (int)dp[startRow, startCol, cutsLeft];
 
        long ans = 0;
 
        // Loop for vertical cuts
        for (int row = startRow; row < m - 1; row++)
        {
            bool upperHalfValid = IsValid(pie, startRow, row, startCol, n - 1);
            bool lowerHalfValid = IsValid(pie, row + 1, m - 1, startCol, n - 1);
 
            if (upperHalfValid && lowerHalfValid)
            {
                int nextWays = Solver(pie, row + 1, startCol, cutsLeft - 1);
                ans = (ans + nextWays) % MOD;
            }
        }
 
        // Loop for horizontal cuts
        for (int col = startCol; col < n - 1; col++)
        {
            bool leftHalfValid = IsValid(pie, startRow, m - 1, startCol, col);
            bool rightHalfValid = IsValid(pie, startRow, m - 1, col + 1, n - 1);
 
            if (leftHalfValid && rightHalfValid)
            {
                int nextWays = Solver(pie, startRow, col + 1, cutsLeft - 1);
                ans = (ans + nextWays) % MOD;
            }
        }
 
        // Store the computed result and return
        return (int)(dp[startRow, startCol, cutsLeft] = ans);
    }
 
    // Main function to calculate ways to cut the pie.
    static int Ways(string[] pie, int P)
    {
        int m = pie.Length, n = pie[0].Length;
 
        // If P is 1, check if the whole pie is valid and return 1 if true, 0 otherwise.
        if (P == 1)
            return IsValid(pie, 0, m - 1, 0, n - 1) ? 1 : 0;
 
        // Initialize DP array with -1 and call the solver function.
        dp = new long[m, n, P];
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                for (int k = 0; k < P; k++)
                {
                    dp[i, j, k] = -1;
                }
            }
        }
 
        int ans = Solver(pie, 0, 0, P - 1);
        return ans;
    }
 
    static void Main()
    {
        string[] pie = { "O..", "OOO", "..." };
        int P = 3;
        Console.WriteLine(Ways(pie, P)); // Print the result
    }
}


Javascript




const MOD = 1000000007;
let dp;
 
// Function to check if there's at least one 'O' in a given sub-matrix.
function isValid(pie, startRow, endRow, startCol, endCol) {
    for (let i = startRow; i <= endRow; i++) {
        for (let j = startCol; j <= endCol; j++) {
            // If there is a pie, return true
            if (pie[i][j] === 'O') {
                return true;
            }
        }
    }
    // No pie found
    return false;
}
// Recursive solver function for the dynamic programming.
function solver(pie, startRow, startCol, cutsLeft) {
    const m = pie.length;
    const n = pie[0].length;
    if (cutsLeft === 0) {
        return 1;
    }
    // If this state has been computed before
    // return the stored value.
    if (dp[startRow][startCol][cutsLeft] !== -1) {
        return dp[startRow][startCol][cutsLeft];
    }
    let ans = 0;
    // Loop for vertical cuts
    for (let row = startRow; row < m - 1; row++) {
        const upperHalfValid = isValid(pie, startRow, row, startCol, n - 1);
        const lowerHalfValid = isValid(pie, row + 1, m - 1, startCol, n - 1);
        if (upperHalfValid && lowerHalfValid) {
            const nextWays = solver(pie, row + 1, startCol, cutsLeft - 1);
            ans = (ans + nextWays) % MOD;
        }
    }
    // Loop for horizontal cuts
    for (let col = startCol; col < n - 1; col++) {
        const leftHalfValid = isValid(pie, startRow, m - 1, startCol, col);
        const rightHalfValid = isValid(pie, startRow, m - 1, col + 1, n - 1);
        if (leftHalfValid && rightHalfValid) {
            const nextWays = solver(pie, startRow, col + 1, cutsLeft - 1);
            ans = (ans + nextWays) % MOD;
        }
    }
    // Store the computed result and return
    dp[startRow][startCol][cutsLeft] = ans;
    return ans;
}
// Main function to calculate ways to cut the pie.
function GFG(pie, P) {
    const m = pie.length;
    const n = pie[0].length;
    if (P === 1) {
        return isValid(pie, 0, m - 1, 0, n - 1) ? 1 : 0;
    }
    // Initialize DP array with -1 and
    // call the solver function.
    dp = new Array(m).fill().map(() => new Array(n).fill().map(() => new Array(P).fill(-1)));
    const ans = solver(pie, 0, 0, P - 1);
    return ans;
}
// Example usage
const pie = ["O..", "OOO", "..."];
const P = 3;
console.log(GFG(pie, P));


Output

3








Time Complexity: O(m*n*P2) where m is the number of rows, n is the number of columns, and P is the number of pieces to cut.
Space Complexity: O(m*n*P) due to the 3D DP array.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads