Number of Ways of Cutting a Pizza

Number of Ways of Cutting a Pizza

Leetcode Daily Challenge (31th March, 2023)

Problem Statement:-

Given a rectangular pizza represented as a rows x cols matrix containing the following characters: 'A' (an apple) and '.' (empty cell) and given the integer k. You have to cut the pizza into k pieces using k-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 pizza into two pieces. If you cut the pizza vertically, give the left part of the pizza to a person. If you cut the pizza horizontally, give the upper part of the pizza to a person. Give the last piece of pizza to the last person.

Return the number of ways of cutting the pizza such that each piece contains at least one apple. Since the answer can be a huge number, return this modulo 10^9 + 7.

Link: https://leetcode.com/problems/number-of-ways-of-cutting-a-pizza/

Problem Explanation with examples:-

Example 1

Input: pizza = ["A..","AAA","..."], k = 3
Output: 3 
Explanation: The figure above shows the three ways to cut the pizza. Note that pieces must contain at least one apple.

Example 2

Input: pizza = ["A..","AA.","..."], k = 3
Output: 1
Explanation: For every person to eat one piece of pizza, there needs to be one piece of pizza. There is only one way to cut the pizza into 3 pieces.

Example 3

Input: pizza = ["A..","A..","..."], k = 1
Output: 1
Explanation: There is only one way to cut the pizza into 1 piece.

Constraints

  • 1 <= rows, cols <= 50

  • rows == pizza.length

  • cols == pizza[i].length

  • 1 <= k <= 10

  • pizza consists of characters 'A' and '.' only.

Intuition:-

  • It is a 3D DP problem.

  • We can use a 3D dp array to store the result.

  • dp[k][r][c] stores the number of ways to cut the pizza into k pieces starting from the cell (r,c).

  • We can use a 2D preSum array to store the number of apples in the pizza.

  • preSum[r][c] stores the number of apples in the pizza starting from the cell (r,c).

  • Loop over rows and columns in reverse order and calculate the preSum array.

  • Then dp function will return the number of ways to cut the pizza into k pieces starting from the cell (r,c).

Solution:-

  • Create a m, n and MOD variable and store the length of the pizza, the length of the pizza and 10^9 + 7 respectively.

  • Create a preSum array and initialize it with 0.

  • Loop over rows and columns in reverse order.

  • Calculate the preSum array by adding the current cell with the right cell, the bottom cell and the bottom right cell and subtracting the bottom right cell.

  • Create a dp function which takes k, r and c as parameters.

  • Check if the preSum[r][c] is 0, if it is return 0.

  • Check if k is 0, if it is return 1.

  • Create an ans variable and initialize it with 0.

  • Loop over the rows from r + 1 to m.

  • Check if the preSum[r][c] - preSum[nr][c] is greater than 0.

  • If it is, add the result of the dp function with k - 1, nr and c to the ans variable.

  • Loop over the columns from c + 1 to n.

  • Check if the preSum[r][c] - preSum[r][nc] is greater than 0.

  • If it is, add the result of the dp function with k - 1, r and nc to the ans variable.

  • Return the ans variable.

  • Return the result of the dp function with K - 1, 0 and 0.

Code:-

JAVA Solution

class Solution {
    public int ways(String[] pizza, int k) {
        int m = pizza.length, n = pizza[0].length();
        Integer[][][] dp = new Integer[k][m][n];
        int[][] preSum = new int[m+1][n+1];

        for (int r = m - 1; r >= 0; r--)
            for (int c = n - 1; c >= 0; c--)
                preSum[r][c] = preSum[r][c+1] + preSum[r+1][c] - preSum[r+1][c+1] + (pizza[r].charAt(c) == 'A' ? 1 : 0);

        return dfs(m, n, k-1, 0, 0, dp, preSum);
    }

    int dfs(int m, int n, int k, int r, int c, Integer[][][] dp, int[][] preSum) {
        if (preSum[r][c] == 0) return 0; 
        if (k == 0) return 1;
        if (dp[k][r][c] != null) return dp[k][r][c];
        int ans = 0;

        for (int nr = r + 1; nr < m; nr++) 
            if (preSum[r][c] - preSum[nr][c] > 0)
                ans = (ans + dfs(m, n, k - 1, nr, c, dp, preSum)) % 1_000_000_007;
        for (int nc = c + 1; nc < n; nc++) 
            if (preSum[r][c] - preSum[r][nc] > 0)
                ans = (ans + dfs(m, n, k - 1, r, nc, dp, preSum)) % 1_000_000_007;

        return dp[k][r][c] = ans;
    }
}

Python Solution

class Solution:
    def ways(self, pizza: List[str], K: int) -> int:
        m, n, MOD = len(pizza), len(pizza[0]), 10 ** 9 + 7
        preSum = [[0] * (n + 1) for _ in range(m + 1)]

        for r in range(m - 1, -1, -1):
            for c in range(n - 1, -1, -1):
                preSum[r][c] = preSum[r][c + 1] + preSum[r + 1][c] - preSum[r + 1][c + 1] + (pizza[r][c] == 'A')

        @lru_cache(None)
        def dp(k, r, c):
            if preSum[r][c] == 0: return 0
            if k == 0: return 1
            ans = 0

            for nr in range(r + 1, m):
                if preSum[r][c] - preSum[nr][c] > 0:
                    ans = (ans + dp(k - 1, nr, c)) % MOD                 
            for nc in range(c + 1, n):
                if preSum[r][c] - preSum[r][nc] > 0:
                    ans = (ans + dp(k - 1, r, nc)) % MOD

            return ans

        return dp(K - 1, 0, 0)

Complexity Analysis:-

TIME:-

  • The preSum array is created in O(m*n) time.

  • The dp function is called at most K * mn times, and each call takes O(m+n) time to execute.

  • The @lru_cache decorator memoizes previous function calls, which makes the subsequent calls O(1).

Therefore, the overall time complexity of the function is O(K * mn), where K is the number of cuts to make in the pizza.

SPACE:-

  • The preSum array requires O(mn) space.

  • The dp function uses the @lru_cache decorator for memoization, which can store up to K * mn previous calls.

  • Since the size of the cache is limited, the space complexity is also O(K * mn).

In conclusion, the function has a time complexity of O(K mn) and a space complexity of O(K mn).

References:-

Connect with me:-

Did you find this article valuable?

Support Leeting-LCS by becoming a sponsor. Any amount is appreciated!