【C++动态规划】2088. 统计农场中肥沃金字塔的数目|2104

【C++动态规划】2088. 统计农场中肥沃金字塔的数目|2104

本文涉及知识点

C++动态规划

LeetCode2088. 统计农场中肥沃金字塔的数目

有一个 矩形网格 状的农场,划分为 m 行 n 列的单元格。每个格子要么是 肥沃的 (用 1 表示),要么是 贫瘠 的(用 0 表示)。网格图以外的所有与格子都视为贫瘠的。
农场中的 金字塔 区域定义如下:
区域内格子数目 大于 1 且所有格子都是 肥沃的 。
金字塔 顶端 是这个金字塔 最上方 的格子。金字塔的高度是它所覆盖的行数。令 (r, c) 为金字塔的顶端且高度为 h ,那么金字塔区域内包含的任一格子 (i, j) 需满足 r <= i <= r + h - 1 且 c - (i - r) <= j <= c + (i - r) 。
一个 倒金字塔 类似定义如下:
区域内格子数目 大于 1 且所有格子都是 肥沃的 。
倒金字塔的 顶端 是这个倒金字塔 最下方 的格子。倒金字塔的高度是它所覆盖的行数。令 (r, c) 为金字塔的顶端且高度为 h ,那么金字塔区域内包含的任一格子 (i, j) 需满足 r - h + 1 <= i <= r 且 c - (r - i) <= j <= c + (r - i) 。
下图展示了部分符合定义和不符合定义的金字塔区域。黑色区域表示肥沃的格子。

在这里插入图片描述


给你一个下标从 0 开始且大小为 m x n 的二进制矩阵 grid ,它表示农场,请你返回 grid 中金字塔和倒金字塔的 总数目 。
示例 1:

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

输入:grid = [[0,1,1,0],[1,1,1,1]]
输出:2
解释:
2 个可能的金字塔区域分别如上图蓝色和红色区域所示。
这个网格图中没有倒金字塔区域。
所以金字塔区域总数为 2 + 0 = 2 。
示例 2:

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

输入:grid = [[1,1,1],[1,1,1]]
输出:2
解释:
金字塔区域如上图蓝色区域所示,倒金字塔如上图红色区域所示。
所以金字塔区域总数目为 1 + 1 = 2 。
示例 3:

在这里插入图片描述

输入:grid = [[1,0,1],[0,0,0],[1,0,1]]
输出:0
解释:
网格图中没有任何金字塔或倒金字塔区域。
示例 4:

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

输入:grid = [[1,1,1,1,0],[1,1,1,1,1],[1,1,1,1,1],[0,1,0,0,1]]
输出:13
解释:
有 7 个金字塔区域。上图第二和第三张图中展示了它们中的 3 个。
有 6 个倒金字塔区域。上图中最后一张图展示了它们中的 2 个。
所以金字塔区域总数目为 7 + 6 = 13.

提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 1000
1 <= m * n <= 105
grid[i][j] 要么是 0 ,要么是 1 。

动态规划

先求正金字塔数量,然后第i行和R-1-i行互换,i $[0,R/2-1],再求正金字塔数量。
#动态规划的装表示
H金字 = min((C+1)/2,R)

动态规划的状态表示

dp[h][r][c]表示 以(r,c)为顶,高度为h的正金子塔是否存在。 空间复杂度:O(RCH)

动态规划的填表顺序

h = 2 To H r = 0 To r+h <= R c to 0 To c+h <= C
dp[h][r][c] = grid[r][c]&&grid[r+1][c]&&[h-1]dp[r+1][c-1]&&dp[h-1][r+1][c+1]
单个状态的时间复杂度:O(1),总时间复杂度:O(RCH)

动态规划的初始化

dp[1] = grid[r][c]
可用滚动向量

动态规划的返回值

dp[2…H]之和。

代码

核心代码

classSolution{public:intcountPyramids(vector<vector<int>>& grid){constint R = grid.size();auto rev = grid;for(int r =0; r < R /2; r++){ rev[r].swap(rev[R -1- r]);}returnDo(grid)+Do(rev);}intDo(const vector<vector<int>>& grid){constint R = grid.size();constint C = grid[0].size();constint H =min(R,(C +1)/2);auto pre = grid;int ans =0;for(int h =2; h <= H; h++){ vector<vector<int>>cur(R,vector<int>(C));for(int r =0; r+ h <= R ;r++)for(int c = h-1; c + h <= C; c++){ cur[r][c]= pre[r][c]&& pre[r +1][c -1]&& pre[r +1][c]&& pre[r +1][c +1]; ans += cur[r][c];} pre.swap(cur);}return ans;}};

单元测试

vector<vector<int>> grid;TEST_METHOD(TestMethod11){ grid ={{0,1,1,0},{1,1,1,1}};auto res =Solution().countPyramids(grid);AssertEx(2, res);}TEST_METHOD(TestMethod12){ grid ={{1,1,1},{1,1,1}};auto res =Solution().countPyramids(grid);AssertEx(2, res);}TEST_METHOD(TestMethod13){ grid ={{1,0,1},{0,0,0},{1,0,1}};auto res =Solution().countPyramids(grid);AssertEx(0, res);}TEST_METHOD(TestMethod14){ grid ={{1,1,1,1,0},{1,1,1,1,1},{1,1,1,1,1},{0,1,0,0,1}};auto res =Solution().countPyramids(grid);AssertEx(13, res);}TEST_METHOD(TestMethod15){ grid.assign(1000,vector<int>(100,1));auto res =Solution().countPyramids(grid);AssertEx(4816700, res);}

优化

如果(r,c,h)是金子塔,则(r,c,h-1)也是金子塔。

动态规划的状态表示

dp[r][c]记录最大h。空间复杂度:O(mn)

动态规划的填表顺序

r = R-2 to 0 c = 1 to C-2

动态规划的转移方程

{ d p [ r ] [ c ] = 0 0 = = g r i d [ r ] [ c ] d p [ r ] [ c ] = 1 + m i n ( d p [ r + 1 ] [ c − 1 ] + d p [ r + 1 ] [ c ] + d p [ r + 1 ] [ c + 1 ] ) o t h e r \begin{cases} dp[r][c] = 0 && 0 == grid[r][c] \\ dp[r][c] = 1 +min(dp[r+1][c-1]+dp[r+1][c]+dp[r+1][c+1]) && other\\ \end{cases} {dp[r][c]=0dp[r][c]=1+min(dp[r+1][c−1]+dp[r+1][c]+dp[r+1][c+1])​​0==grid[r][c]other​
空间复杂度:O(mn)

动态规划的初始值

dp = grid

动态规划的返回值

dp之和-gird之和

代码

classSolution{public:intcountPyramids(vector<vector<int>>& grid){constint R = grid.size();auto rev = grid;for(int r =0; r < R /2; r++){ rev[r].swap(rev[R -1- r]);}returnDo(grid)+Do(rev);}intDo(const vector<vector<int>>& grid){constint R = grid.size();constint C = grid[0].size();auto dp = grid;for(int r = R-2;r >=0; r--)for(int c =1; c < C -1; c++){if(0== grid[r][c]){continue;} dp[r][c]=1+*min_element(dp[r+1].begin()+ c -1, dp[r+1].begin()+ c +2);}int ans =0;for(constauto& v : dp){ ans +=accumulate(v.begin(), v.end(),0);}for(constauto& v : grid){ ans -=accumulate(v.begin(), v.end(),0);}return ans;}};

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步ZEEKLOG学院,听白银讲师(也就是鄙人)的讲解。
https://edu.ZEEKLOG.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.ZEEKLOG.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

Read more

星标超 28 万,OpenClaw 两天两次大更!适配GPT 5.4,告别“抽卡式 Prompt”

星标超 28 万,OpenClaw 两天两次大更!适配GPT 5.4,告别“抽卡式 Prompt”

整理 | 梦依丹 出品 | ZEEKLOG(ID:ZEEKLOGnews) “We don’t do small releases.” 这是 OpenClaw 在发布 2026.3.7 版本时写下的一句话。 刚刚过去的周六与周日,这个 GitHub 星标已超 28 万 的 AI Agent 开源项目再次迎来两轮重量级更新。 两天两次更新:OpenClaw 做了一次“真正的大版本升级” 打开 OpenClaw 的 GitHub 更新日志,你会发现这次版本更新的规模确实不小。在 3 月 7 日发布更新后,第二天又迅速推出 2026.3.8-beta.1 和

By Ne0inhk
为省5-10美元差点毁库!Claude一条指令删光200万条数据、网站停摆24小时,创始人坦言:全是我的错

为省5-10美元差点毁库!Claude一条指令删光200万条数据、网站停摆24小时,创始人坦言:全是我的错

编译 | 屠敏 出品 | ZEEKLOG(ID:ZEEKLOGnews) AI 时代,一次看似普通的操作,竟能让整套生产环境与近 200 万条数据瞬间「归零」。 近日,数据科学社区 DataTalks.Club 创始人 Alexey Grigorev 就遭遇了这样的惊魂时刻,他在使用 AI 编程工具 Claude Code 管理网站服务器时,意外清空了平台积累 2.5 年的核心数据,甚至连数据库快照也未能幸免,导致网站停摆整整 24 小时。 这起事故不仅在开发者社区引发热议,更给所有依赖 AI 工具与自动化运维的从业者敲响了警钟。事后,Alexey Grigorev 公开复盘了整个过程,并揭露了此次事故的核心问题。让我们一起看看。 一次看似很普通的网站迁移 这场“删库”事件的前因,其实并不复杂。

By Ne0inhk
苹果最贵手机要来了!折叠屏iPhone将于9月亮相;部分高校严禁校内使用OpenClaw;黄仁勋预言:传统软件和APP或将消失 | 极客头条

苹果最贵手机要来了!折叠屏iPhone将于9月亮相;部分高校严禁校内使用OpenClaw;黄仁勋预言:传统软件和APP或将消失 | 极客头条

「极客头条」—— 技术人员的新闻圈! ZEEKLOG 的读者朋友们好,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧。(投稿或寻求报道:[email protected]) 整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 一分钟速览新闻点! * 多所高校要求警惕 OpenClaw 安全风险,部分严禁校内使用 * 荣耀 CEO 李健:荣耀机器人全栈自研,将聚焦消费市场 * 马化腾凌晨 2 点发声:还有一批龙虾系产品陆续赶来 * 前快手语言大模型中心负责人张富峥,已加入智源人工智能研究院,负责 LLM 方向 * 最新全球 AI 应用百强榜发布,豆包/DeepSeek/千问上榜 * 苹果折叠 iPhone 将于九月亮相,融合 iPhone 与 iPad 体验

By Ne0inhk
不止“996”!曝硅谷AI创业圈「极限工作制」:每天16小时、凌晨3点下班、周末也在写代码

不止“996”!曝硅谷AI创业圈「极限工作制」:每天16小时、凌晨3点下班、周末也在写代码

编译 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) “如果你周日去旧金山的咖啡馆,会发现几乎每个人都在工作。” 这是 AI 创业公司 Mythril 联合创始人 Sanju Lokuhitige 最近最直观的感受。去年 11 月,他特地搬到旧金山,只为了更接近 AI 创业浪潮的中心。但很快,他也被卷入了这股浪潮带来的另一面——一种越来越极端的工作文化。 Lokuhitige 坦言,他现在几乎每天工作 12 小时,每周 7 天。除了每周少数几场刻意安排的社交活动(主要是为了和创业者们建立联系),其余时间几乎都在写代码、做产品。 “有时候我整整一天都在编程,”他说,“我基本没有什么工作与生活的平衡。”而这样的生活,在如今的 AI 创业圈里并不算罕见。 旧金山 AI 创业圈的真实日常 一位在旧金山一家 AI

By Ne0inhk