全零子矩阵计数算法解析及修正
我来帮你分析这段代码的问题并修正。 ## 🔍 问题分析 这段代码尝试用**单调栈**方法计算所有可能的矩形数量,但存在几个关键错误: ### ❌ 主要错误 1. **高度计算方式错误**:不是简单的非*就加1,而是需要统计连续`.`的高度 2. **矩形计数逻辑错误**:题目要求统计所有不含`*`的矩形,不是柱状图中的矩形 3. **计数重复问题**:单调栈方法容易造成重复计数 ## 📐 正确解法思路 这是一个典型的**统计全0子矩阵个数**问题,可以用**动态规划+单调栈**解决: ```cpp #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); int n, m; cin >> n >> m; vector<vector<char>> grid(n, vector<char>(m)); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { cin >> grid[i][j]; } } // height[j] 表示以当前行作为底边,从下往上连续'.'的个数 vector<int> height(m, 0); long long total = 0; for (int i = 0; i < n; ++i) { // 更新每一列的连续高度 for (int j = 0; j < m; ++j) { if (grid[i][j] == '.') { height[j]++; } else { height[j] = 0; } } // 使用单调栈统计以当前行为底边的矩形个数 stack<int> st; // 使用前缀和方法更简单 vector<int> left(m, -1), right(m, m); // 计算左边界 for (int j = 0; j < m; ++j) { while (!st.empty() && height[st.top()] >= height[j]) { st.pop(); } left[j] = st.empty() ? -1 : st.top(); st.push(j); } // 清空栈,计算右边界 while (!st.empty()) st.pop(); for (int j = m - 1; j >= 0; --j) { while (!st.empty() && height[st.top()] > height[j]) { st.pop(); } right[j] = st.empty() ? m : st.top(); st.push(j); } // 统计以当前行为底边的矩形数量 for (int j = 0; j < m; ++j) { if (height[j] > 0) { // 以height[j]作为矩形高度,可选择的宽度为 (j - left[j]) * (right[j] - j) long long leftWays = j - left[j]; long long rightWays = right[j] - j; total += height[j] * leftWays * rightWays; } } } cout << total << "\n"; return 0; } ``` ## 📊 算法思路说明 1. **逐行处理**:从上到下遍历每一行,作为矩形的底边 2. **维护高度数组**:`height[j]`表示从当前行向上连续`.`的个数 3. **单调栈找边界**: - `left[j]`:左边第一个高度小于`height[j]`的列索引 - `right[j]`:右边第一个高度小于`height[j]`的列索引 4. **计算矩形数**:对于每个`height[j] > 0`的列,可以形成的高度为1到`height[j]`,宽度为`(j - left[j]) * (right[j] - j)`个可能的矩形 ## ⚠️ 关键注意事项 1. **数据类型**:结果可能很大,使用`long long` 2. **边界处理**:左右边界分别设置为`-1`和`m` 3. **高度计算**:遇到`*`时重置为0,而不是简单累加 ## 💡 优化建议 - 可以添加`#include <iostream>`和`#include <vector>`替代`bits/stdc++.h`以提高编译速度 - 考虑使用`#pragma GCC optimize("O3")`优化性能 - 对于大规模数据(1000×1000),当前算法复杂度为O(n×m),已经是最优解 ######[AI写代码神器 | 1011点数解答 | 2026-06-14 20:01:32]
- C++ 实现:轻松计算两个矩阵的乘法并输出结果(字节豆包 | 381点数解答 | 2025-12-03 19:20:23)177
- Golang开发:解析JSON数据时数值默认类型及示例解析(百度文心 | 393点数解答 | 2023-11-09 18:13:06)334
- SQL Working Areas Sizing: Manual vs. Automatic Policy - A Comprehensive Analysis(阿里通义 | 530点数解答 | 2024-05-13 10:55:58)353
- Python 实现:根据规则判定 2^n×2^n 方阵中作弊者的赦免命运(字节豆包 | 247点数解答 | 2024-11-03 10:30:46)225
- C语言实现:解决2ⁿ×2ⁿ方阵作弊者赦免问题(字节豆包 | 370点数解答 | 2024-11-03 10:31:31)242
- C语言递归破解2ⁿ×2ⁿ作弊者赦免难题,输出01命运矩阵!(百度文心 | 792点数解答 | 2024-11-03 10:36:04)308
- Python 实现:计算用户输入 n x n 矩阵边界元素之和(GPT | 319点数解答 | 2024-11-21 00:16:05)159
- DevC++ 实现:计算并输出 n×n 矩阵边界元素之和(GPT | 410点数解答 | 2024-11-21 00:19:17)164
- 月赛作弊者命运裁决:2^n×2^n 方阵赦免递归算法揭秘(DeepSeek | 483点数解答 | 2026-01-05 12:24:54)71
- Python 实现:计算特殊规则矩阵行列式并对 109+7 取模(字节豆包 | 672点数解答 | 2026-02-05 20:46:07)97
- C++实现自动化药房配药检查功能(字节豆包 | 701点数解答 | 2026-03-08 10:23:41)45
- Python切片操作巧解经典算法:二维数组90°旋转(阿里通义 | 205点数解答 | 2023-10-31 11:05:29)362