牛客网-魔法之森的蘑菇(二)

208 阅读6分钟

本题自己没有写出来,借助ai刷题里的ai讲解思路完成的 题目 链接:ac.nowcoder.com/acm/contest…
来源:牛客网

小红在魔法之森迷路了,森林中有一些致幻的毒蘑菇。森林用一个 nnn 行 mmm 列的矩阵表示。
小红准备采集一个矩形区域里的资源,但小红非常讨厌蘑菇,因此她希望这个矩形内没有任何蘑菇。
小红希望你帮她计算出一个面积最大的、且不包含蘑菇的矩形区域。

输入描述:

第一行输入两个正整数n,mn,mn,m,代表矩阵的行数和列数。
接下来的nnn行,每行输入一个长度为mmm的字符串,用来表示森林地图。
保证所有的字符仅有'.''*'这两种,其中'.'代表道路,'*'代表蘑菇。
1≤n,m≤301\leq n,m \leq 301≤n,m≤30

输出描述:

四个整数x1,y1,x2,y2x_1,y_1,x_2,y_2x1​,y1​,x2​,y2​,用空格隔开。代表矩形的左上角在第x1x_1x1​行第y1y_1y1​列,右下角在第x2x_2x2​行第y2y_2y2​列。保证至少有一个合法的答案。

思路 这个问题可以看作是一个最大子矩形问题,但有一个额外的限制条件:矩形区域内不能包含蘑菇。我们可以使用动态规划来解决这个问题。

解题思路

理解问题

需要找到一个最大的矩形区域,该区域内没有任何蘑菇。

输出该矩形的左上角和右下角的坐标。

数据结构选择

使用一个二维数组 dp 来记录每个位置向上连续的'.'的数量。

使用一个栈来辅助计算最大矩形面积。

算法步骤

首先,遍历矩阵,计算每个位置向上连续的'.'的数量,存储在 dp 数组中。

然后,对于每一列,使用栈来计算以该列为底边的最大矩形面积。

记录最大面积及其对应的矩形坐标。

代码框架

这个问题可以看作是一个最大子矩形问题,但有一个额外的限制条件:矩形区域内不能包含蘑菇。我们可以使用动态规划来解决这个问题。

解题思路

理解问题

需要找到一个最大的矩形区域,该区域内没有任何蘑菇。

输出该矩形的左上角和右下角的坐标。

数据结构选择

使用一个二维数组 dp 来记录每个位置向上连续的'.'的数量。

使用一个栈来辅助计算最大矩形面积。

算法步骤

首先,遍历矩阵,计算每个位置向上连续的'.'的数量,存储在 dp 数组中。

然后,对于每一列,使用栈来计算以该列为底边的最大矩形面积。

记录最大面积及其对应的矩形坐标。

解释

dp数组:记录每个位置向上连续的'.'的数量。

栈的使用:用于计算以当前列为底边的最大矩形面积。

结果记录:记录最大面积及其对应的矩形坐标。

这个框架可以帮助你理解如何实现这个问题的解决方案。你可以根据这个框架继续完善代码。

这个问题可以看作是一个最大子矩形问题,但有一个额外的限制条件:矩形区域内不能包含蘑菇。我们可以使用动态规划来解决这个问题。

解题思路

理解问题

需要找到一个最大的矩形区域,该区域内没有任何蘑菇。

输出该矩形的左上角和右下角的坐标。

数据结构选择

使用一个二维数组 dp 来记录每个位置向上连续的'.'的数量。

使用一个栈来辅助计算最大矩形面积。

算法步骤

首先,遍历矩阵,计算每个位置向上连续的'.'的数量,存储在 dp 数组中。

然后,对于每一列,使用栈来计算以该列为底边的最大矩形面积。

记录最大面积及其对应的矩形坐标。

代码框架

#include #include #include #include using namespace std; vector maxRectangle(vector<vector>& matrix) { int n = matrix.size(); int m = matrix[0].size(); vector<vector> dp(n, vector(m, 0)); // 计算每个位置向上连续的'.'的数量 for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (matrix[i][j] == '.') { dp[i][j] = (i == 0) ? 1 : dp[i-1][j] + 1; } } } int maxArea = 0; vector result(4, 0); // 对于每一列,计算以该列为底边的最大矩形面积 for (int i = 0; i < n; ++i) { stack s; vector left(m, 0), right(m, m); for (int j = 0; j < m; ++j) { while (!s.empty() && dp[i][s.top()] >= dp[i][j]) { s.pop(); } left[j] = s.empty() ? 0 : s.top() + 1; s.push(j); } while (!s.empty()) s.pop(); for (int j = m - 1; j >= 0; --j) { while (!s.empty() && dp[i][s.top()] >= dp[i][j]) { s.pop(); } right[j] = s.empty() ? m : s.top(); s.push(j); } for (int j = 0; j < m; ++j) { int area = dp[i][j] * (right[j] - left[j]); if (area > maxArea) { maxArea = area; result = {left[j], i - dp[i][j] + 1, right[j] - 1, i}; } } } return result; } int main() { int n, m; cin >> n >> m; vector<vector> matrix(n, vector(m)); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { cin >> matrix[i][j]; } } vector result = maxRectangle(matrix); cout << result[1] + 1 << " " << result[0] + 1 << " " << result[3] + 1 << " " << result[2] + 1 << endl; return 0; }

解释

dp数组:记录每个位置向上连续的'.'的数量。

栈的使用:用于计算以当前列为底边的最大矩形面积。

结果记录:记录最大面积及其对应的矩形坐标。

这个框架可以帮助你理解如何实现这个问题的解决方案。你可以根据这个框架继续完善代码。

注意

请使用用户提问的语言回答。

用户提问对象为「当前代码」、「我的代码」或对应的英文表述时,请根据「编辑区代码」部分的内容回答,请不要解释「题目内容」中的代码。

请优先回答「编辑区代码」

解释

dp数组:记录每个位置向上连续的'.'的数量。

栈的使用:用于计算以当前列为底边的最大矩形面积。

结果记录:记录最大面积及其对应的矩形坐标。

这个框架可以帮助你理解如何实现这个问题的解决方案。你可以根据这个框架继续完善代码。 在代码中 for (int j = 0; j < m; ++j) { while (!s.empty() && dp[i][s.top()] >= dp[i][j]) { s.pop(); } left[j] = s.empty() ? 0 : s.top() + 1; s.push(j); } while (!s.empty()) s.pop(); for (int j = m - 1; j >= 0; --j) { while (!s.empty() && dp[i][s.top()] >= dp[i][j]) { s.pop(); } right[j] = s.empty() ? m : s.top(); s.push(j); } 这里很巧,第一次如果保留dp,下一次会与其相反的保留dp来找到解决问题 做这种题的时候遇到二维数组就想到dp并没有很好的解决问题,没有运用到栈就是没能理解连接关系以及缺乏前缀关系和后缀关系的思想,前后遍历之后的维护很重要,