目录

1444:切披萨的方案数(2126 分)

力扣第 188 场周赛第 4 题

题目

给你一个 rows x cols 大小的矩形披萨和一个整数 k ,矩形包含两种字符: 'A' (表示苹果)和 '.' (表示空白格子)。你需要切披萨 k-1 次,得到 k 块披萨并送给别人。

切披萨的每一刀,先要选择是向垂直还是水平方向切,再在矩形的边界上选一个切的位置,将披萨一分为二。如果垂直地切披萨,那么需要把左边的部分送给一个人,如果水平地切,那么需要把上面的部分送给一个人。在切完最后一刀后,需要把剩下来的一块送给最后一个人。

请你返回确保每一块披萨包含 至少 一个苹果的切披萨方案数。由于答案可能是个很大的数字,请你返回它对 10^9 + 7 取余的结果。

示例 1:

输入:pizza = ["A..","AAA","..."], k = 3
输出:3
解释:上图展示了三种切披萨的方案。注意每一块披萨都至少包含一个苹果。

示例 2:

输入:pizza = ["A..","AA.","..."], k = 3
输出:1

示例 3:

输入:pizza = ["A..","A..","..."], k = 1
输出:1

提示:

  • 1 <= rows, cols <= 50
  • rows == pizza.length
  • cols == pizza[i].length
  • 1 <= k <= 10
  • pizza 只包含字符 'A''.'

相似问题:

分析

#1

  • 为了方便,可以将行和列都反序
  • 按切线递推即可
  • 可以预处理二维前缀和,快速判断切下的一块是否有苹果
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution:
    def ways(self, pizza: List[str], k: int) -> int:
        mod = 10**9+7
        A = [[int(a=='A') for a in row[::-1]] for row in pizza[::-1]]
        m,n = len(A),len(A[0])
        h = [[0]*(n+1) for _ in range(m+1)]
        f = [[0]*(n+1) for _ in range(m+1)]
        for i in range(1,m+1):
            for j in range(1,n+1):
                h[i][j] = h[i][j-1]+h[i-1][j]-h[i-1][j-1]+A[i-1][j-1]
                f[i][j] = int(h[i][j]>0)
        for _ in range(k-1):
            g = [[0]*(n+1) for _ in range(m+1)]
            for i in range(1,m+1):
                for j in range(1,n+1):
                    s = 0
                    for x in range(i):
                        if h[i][j]>h[x][j]:
                            s += f[x][j]
                    for y in range(j):
                        if h[i][j]>h[i][y]:
                            s += f[i][y]
                    g[i][j] = s%mod
            f = g
        return f[-1][-1]

59 ms

#2

  • 注意递推式,找到最大的 y 使得 h[i][j]>h[i][y],那么就是求 f[i][:y+1] 的前缀和
  • 因此,可以预处理 f 按行/列的前缀和,优化时间

解答

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution:
    def ways(self, pizza: List[str], k: int) -> int:
        mod = 10**9+7
        A = [[int(a=='A') for a in row[::-1]] for row in pizza[::-1]]
        m,n = len(A),len(A[0])
        h = [[0]*(n+1) for _ in range(m+1)]
        f = [[0]*(n+1) for _ in range(m+1)]
        for i in range(1,m+1):
            for j in range(1,n+1):
                h[i][j] = h[i][j-1]+h[i-1][j]-h[i-1][j-1]+A[i-1][j-1]
                f[i][j] = int(h[i][j]>0)
        for _ in range(k-1):
            R = [[0]*(n+1) for _ in range(m+1)]
            C = [[0]*(m+1) for _ in range(n+1)]
            g = [[0]*(n+1) for _ in range(m+1)]
            for i in range(1,m+1):
                for j in range(1,n+1):
                    if h[i][j]==h[i-1][j]:
                        g[i][j] = g[i-1][j]
                    elif h[i][j]==h[i][j-1]:
                        g[i][j] = g[i][j-1]
                    else:
                        g[i][j] = (R[i][j-1]+C[j][i-1])%mod
                    R[i][j] = (R[i][j-1]+f[i][j])%mod
                    C[j][i] = (C[j][i-1]+f[i][j])%mod
            f = g
        return f[-1][-1]

6 ms