csp B4415

0 阅读2分钟

题目:给定一个 n × m 的网格,每个格子是 0 或 1。要找到一个只包含 1 的矩形区域,使得这个矩形包含的格子数最多。输出最大面积。 如果我们固定矩形的底部在第 i 行,那么问题就变成了: 每一列向上连续 1 的个数构成一个直方图 我们需要在这个直方图中找最大矩形面积 首先,从第一行开始逐步循环 1.找出每一次循环每一列的1的数量; 2.设置一个栈; 3.从第一列开始循环,找到j列比栈顶小的地方,即right(但不包含j列); 4.找到之后,开始计算面积;高度是栈顶的高度,然后踢出栈顶,宽度应该找一下左边的那一列是多少: 左边的那一列应该是现在的栈顶,如果现在的栈顶是空,则width是j前面的列;按要求循环; 5.所有循环完后,如果栈不为空,说明最后存在几列是递增的,在计算面积;

第一步:将二维问题转化为一维直方图问题

逐行扫描矩阵,维护一个 height 数组,height[j] 表示第 j 列从当前行向上连续 1 的个数。

  • 如果当前格子是 1,则 height[j]++
  • 如果当前格子是 0,则 height[j] = 0

这样每一行都得到一个直方图,问题转化为:在直方图中找最大矩形面积


第二步:用单调栈求直方图的最大矩形

单调栈的核心思想:维护一个高度递增的栈,存储列下标

具体步骤:

  1. 初始化一个空栈

  2. 遍历每一列 j(0 到 m-1)

    • 当栈非空且 height[j] < height[栈顶] 时,说明栈顶柱子的右边界已经确定(就是当前列 j),需要弹出栈顶并计算面积:
          • 高度 = height[栈顶]
      • 左边界 = 栈中下一个元素(如果栈空则为 -1)
      • 宽度 = j - 左边界 - 1
      • 面积 = 高度 × 宽度
      • 更新最大面积
    • 将当前列 j 入栈
  3. 遍历结束后,处理栈中剩余元素

    • 这些柱子右边没有更矮的柱子,可以一直延伸到最后一列
    • 右边界 = m(最后一列 + 1)
    • 宽度 = m - 左边界 - 1
    • 同样计算面积并更新最大值

第三步:更新全局最大面积

每一行计算完后,用该行的最大面积更新全局最大值,最后输出结果。