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
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:
#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
} |
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 |
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
|
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
}
} |
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)); |
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.