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

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

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



解题思路:
下面两张图展示了每次切披萨的时候面临的两种选择:水平切和竖直切(由于版面限制,呈现在两张图中)。阴影部分是一刀切下后,能即刻分到的披萨,每次切需要保证即刻分得的披萨内部“A”的数量至少为1(“A”即Apple)。第二张图中蓝色阴影内“A”数量为0,为不合法的切割方式。
切割后,剩余披萨是否合法,需要看所剩披萨内“A”的数目是否不小于尚未分得披萨人数,如果小于则不合法。


但可能存在重叠的子问题,增加算法时间复杂度,如下图。

采用一般的动态规划dp[index][iterator]思想。
dp[m][n][k]前两个维度是坐标,最后一个维度是cuts数,用来表示右下角的pizza切k cuts有多少种合法的切法。如果k=0,则表示一刀不切时,这块pizza是否合法(即是否至少含一个苹果),此时也是递归问题的base case
def dp[m][n][k]:
if k==0:return 1 if hasApple(pizza[m:M][n:N]) else 0.

class Solution {public:int ways(vector<string>& pizza, int K) {int kMod=1e9+7;int M=pizza.size();int N=pizza[0].size();vector<vector<int>> presum(M+1,vector<int>(N+1));for(int i=0;i<M;i++){for(int j=0;j<N;j++){presum[i+1][j+1]=presum[i][j+1]+presum[i+1][j]-presum[i][j]+(pizza[i][j]=='A');}}//左上角前缀和auto hasApples=[&](int x1,int y1,int x2,int y2){return presum[x2+1][y2+1]-presum[x1][y2+1]-presum[x2+1][y1]+presum[x1][y1]>0;};//求解任意一个子矩阵是否有苹果vector<vector<vector<int>>> cache(M,vector<vector<int>> (N,vector<int>(K,-1)));function<int(int,int,int)> dp=[&](int m,int n,int k)->int{if(k==0)    return hasApples(m,n,M-1,N-1);int res=cache[m][n][k];if(res!=-1) return res;res=0;for(int x=m;x<M-1;x++){res=(res+hasApples(m,n,x,N-1)*dp(x+1,n,k-1))%kMod;}for(int y=n;y<M-1;y++){res=(res+hasApples(m,n,M-1,y)*dp(m,y+1,k-1))%kMod;}return res;};return dp(0,0,K-1);}
};

LeetCode 1444. 切披萨的方案数(一)相关推荐

  1. 切披萨n块需要几刀原理c语言,LeetCode 1444. 切披萨的方案数(DP)

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

  2. LeetCode 1444. 切披萨的方案数(DP)

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

  3. LeetCode 2147. 分隔长廊的方案数

    文章目录 1. 题目 2. 解题 1. 题目 在一个图书馆的长廊里,有一些座位和装饰植物排成一列. 给你一个下标从 0 开始,长度为 n 的字符串 corridor ,它包含字母 'S' 和 'P' ...

  4. LeetCode 1976. 到达目的地的方案数(迪杰斯特拉 Python 优先队列)

    文章目录 1. 题目 2. 解题 1. 题目 你在一个城市里,城市由 n 个路口组成,路口编号为 0 到 n - 1 ,某些路口之间有 双向 道路. 输入保证你可以从任意路口出发到达其他任意路口,且任 ...

  5. LeetCode 6061. 买钢笔和铅笔的方案数

    文章目录 1. 题目 2. 解题 1. 题目 给你一个整数 total ,表示你拥有的总钱数.同时给你两个整数 cost1 和 cost2 ,分别表示一支钢笔和一支铅笔的价格. 你可以花费你部分或者全 ...

  6. LeetCode 1664. 生成平衡数组的方案数(前缀和+后缀和)

    文章目录 1. 题目 2. 解题 1. 题目 给你一个整数数组 nums .你需要选择 恰好 一个下标(下标从 0 开始)并删除对应的元素.请注意剩下元素的下标可能会因为删除操作而发生改变. 比方说, ...

  7. LeetCode 1569. 将子数组重新排序得到同一个二叉查找树的方案数(DP)

    文章目录 1. 题目 2. 解题 1. 题目 给你一个数组 nums 表示 1 到 n 的一个排列. 我们按照元素在 nums 中的顺序依次插入一个初始为空的二叉查找树(BST). 请你统计将 num ...

  8. LeetCode 1411. 给 N x 3 网格图涂色的方案数(数学)

    1. 题目 你有一个 n x 3 的网格图 grid ,你需要用 红,黄,绿 三种颜色之一给每一个格子上色,且确保相邻格子颜色不同(也就是有相同水平边或者垂直边的格子颜色不同). 给你网格图的行数 n ...

  9. leetcode 5383. 给 N x 3 网格图涂色的方案数

    leetcode 5383. 给 N x 3 网格图涂色的方案数 来源:力扣(LeetCode) 你有一个 n x 3 的网格图 grid ,你需要用 红,黄,绿 三种颜色之一给每一个格子上色,且确保 ...

最新文章

  1. Django1.11模型使用
  2. halcon算子盘点:Chapter 18:元组Tuple
  3. React 15.5带来重大修改
  4. php session警告屏蔽,PHP Session的一个警告
  5. 一. JVM发展史,运行时数据区域,四大引用
  6. [恢]hdu 2074
  7. [Git] 多个分支修改相同文件
  8. 2022-03-28 术语MES、WMS
  9. 开启关闭Centos的自动更新
  10. linux 交叉编译 makefile,简单谈谈Makefile和交叉编译工具链
  11. 微信隐藏功能系列:微信怎么恢复聊天记录?3步完成修复
  12. 十大语音搜索应用服务(以歌搜歌)
  13. 巴斯大学计算机科学研究生,巴斯大学计算机科学.pdf
  14. 网速/带宽与下载速度对照表
  15. linux锁屏命令 TM,Linux基本命令的使用(上)
  16. 向武 清华大学 计算机,哥哥保送弟弟全市第二 双胞胎同时上清华(组图)
  17. 谈谈eve-ng仿真模器
  18. 将正确的ADC与应用程序匹配
  19. 亚马逊如何创业?身为小白的我适合创业亚马逊吗
  20. RIFF和WAVE文件格式

热门文章

  1. Python 操作数据库
  2. Bootstrap 信息提示框
  3. MSCS仲裁出错不能启动解决
  4. 客户关系管理系统PRD编写
  5. 商城搜索DSL elasticsearch 相关代码
  6. [图像分割综述] Image Segmentation Using Deep Learning: A Survey
  7. PMP项目管理证书难考吗?
  8. PADS 免费视频教程
  9. 40个提升自己编程能力的小技巧
  10. 繁易平台对接阿里云平台: MQTT方式