LeetCode每日一题(1444. Number of Ways of Cutting a Pizza)

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.

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

Example 3:

Input: pizza = [“A…”,“A…”,“…”], k = 1
Output: 1

Constraints:

  • 1 <= rows, cols <= 50
  • rows == pizza.length
  • cols == pizza[i].length
  • 1 <= k <= 10
  • pizza consists of characters ‘A’ and ‘.’ only.

我在任意处切一刀, 只要保证剩余的部分可以再分成 k - 1 份即可

假设剩余的披萨的顶部为 top, 左侧为 left, 那 dp[top][left]就应该等于, 对于任意 top < r <= bottom
水平切的方法数量为, horizontal = sum(dp[r][left]), 对于任意 left < c <= right, 垂直的切法数量为 vertical = sum(dp[top][c]), horizontal + vertical 即为全部的切法。

但是不是每个位置我们都可以下刀的, 我们需要检查切下来拿去分的部分(上半部分或者左半部分)上是不是有苹果, 而且还要保证剩下的部分能够分。 剩余部分好处理, 如果不够分我们直接在递归的过程中返回 0 即可。检查拿去分的部分上面是否有苹果, 我们借助二维的 prefix sum 可以解决



use std::collections::HashMap;

const M: i64 = 1000000007;

impl Solution {
    fn dp(prefix_sum: &Vec<Vec<i32>>, k: i32, top: usize, left: usize, cache: &mut HashMap<(i32, usize, usize), i64>) -> i64 {
        if k == 1 {
            return if Solution::get_apple_count(prefix_sum, top, left, prefix_sum.len() - 1, prefix_sum[0].len() - 1) > 0 {
                1
            } else {
                0
            };
        }
        if let Some(&c) = cache.get(&(k, top, left)) {
            return c;
        }
        let mut ans = 0;
        for bottom in top + 1..prefix_sum.len() {
            if Solution::get_apple_count(prefix_sum, top, left, bottom, prefix_sum[0].len() - 1) > 0 {
                ans += Solution::dp(prefix_sum, k - 1, bottom, left, cache) % M;
                ans %= M;
            }
        }
        for right in left + 1..prefix_sum[0].len() {
            if Solution::get_apple_count(prefix_sum, top, left, prefix_sum.len() - 1, right) > 0 {
                ans += Solution::dp(prefix_sum, k - 1, top, right, cache) % M;
                ans %= M;
            }
        }
        cache.insert((k, top, left), ans);
        ans
    }

    fn get_apple_count(prefix_sum: &Vec<Vec<i32>>, top: usize, left: usize, bottom: usize, right: usize) -> i32 {
        prefix_sum[bottom][right] - prefix_sum[bottom][left] - prefix_sum[top][right] + prefix_sum[top][left]
    }

    pub fn ways(pizza: Vec<String>, k: i32) -> i32 {
        let pizza: Vec<Vec<char>> = pizza.into_iter().map(|s| s.chars().collect()).collect();
        let mut prefix_sum = vec![vec![0; pizza[0].len() + 1]; pizza.len() + 1];
        for r in 0..pizza.len() {
            for c in 0..pizza[0].len() {
                prefix_sum[r + 1][c + 1] = prefix_sum[r][c + 1] + prefix_sum[r + 1][c] - prefix_sum[r][c] + if pizza[r][c] == 'A' { 1 } else { 0 };
            }
        }
        Solution::dp(&prefix_sum, k, 0, 0, &mut HashMap::new()) as i32
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值