C++最大长方形

首先如图所示,在表T中记录各元素向上存在多少个连续的干净瓷砖。对各列使用动态规划法可以很轻松地求出T。在这里插入图片描述
把表T的每行都看成一个直方图,本题就了求直方图内最大长方形的问题,于是我们转为考虑求直方图中最大长方形的面积。这里最容易想到的仍然是穷举法,我们可以列出直方图的所有端点,求出各个范围内的最大长方形的面积(以该范围内最小值为高的长方形的面积)。然后取其中最大值。但是,这个算法套用到原题中的话,整体的复杂度仍高达O(H平方xW),因此还需要再花些心思。
其实在解这个问题的时候,只要用栈替代数组记录局部问题的解,就能大幅提高求最优解的效率。栈中记录“仍有可能扩张的长方形的信息(记为rect)”。rect内含有两个信息,一个是长方形的高 height,另个是其左端的位置pos,首先我们将栈置为空,接下来对直方图的各个值Hi(i=0, 1,…,W-1)。创建以Hi为高,以其下标为左端位置的长方形rect,然后进行以下处理。

  1. 如果栈为空,将rect入栈
  2. 如果栈顶长方形的高小于rect的高,将rect压入栈
  3. 如果栈顶长方形的高等于rect的高,不作处理
  4. 如果栈顶长方形的高大于rect的高, 只要栈不为空,且栈顶长方形的高大于等于rect的高,就从栈中取出长方形,同时计算其面积并更新最大值。长方形的长等于“当前位置与之前记录的“左端位置pos”的差值。将rect压人栈。另外,这个rect的左端位置pos为最后从栈中取出的长方形的pos值,举个例子,直方图{1,3,3,5,7,2}的处理过程如下图所示。在这里插入图片描述

代码:

#include<stdio.h>
#include<iostream>
#include<stack>
#include<algorithm>
#define MAX 1400

using namespace std;

struct Rectangle
{
	int height; int pos;
};

int getLargestRectangle(int size, int buffer[]) {
	stack<Rectangle> S;
	int maxv = 0;
	buffer[size] = 0;

	for (int i = 0; i <= size; i++) {
		Rectangle rect;
		rect.height = buffer[i];
		rect.pos = i;
		if (S.empty()) {
			S.push(rect);
		}
		else {
			if (S.top().height < rect.height) {
				S.push(rect);
			}
			else if (S.top().height > rect.height) {
				int target = i;
				while (!S.empty() && S.top().height >= rect.height) {
					Rectangle pre = S.top(); S.pop();
					int area = pre.height * (i - pre.pos);
					maxv = max(maxv, area);
					target = pre.pos;
				}
				rect.pos = target;
				S.push(rect);
			}
		}
	}
	return maxv;
}

int H, W;
int buffer[MAX][MAX];
int T[MAX][MAX];

int getLargestRectangle() {
	for (int j = 0; j < W; j++) {
		for (int i = 0; i < H; i++) {
			if (buffer[i][j]) {
				T[i][j] = 0;
			}
			else {
				T[i][j] = (i > 0) ? T[i - 1][j] + 1 : 1;
			}
		}
	}
	
	int maxv = 0;
	for (int i = 0; i < H; i++) {
		maxv = max(maxv, getLargestRectangle(W, T[i]));
	}

	return maxv;
}

int main() {
	scanf_s("%d %d", &H, &W);
	for (int i = 0; i < H; i++) {
		for (int j = 0; j < W; j++) {
			scanf_s("%d", &buffer[i][j]);
		}
	}
	cout << getLargestRectangle() << endl;

	system("pause");
	return 0;

在这里插入图片描述

发布了54 篇原创文章 · 获赞 17 · 访问量 9198

猜你喜欢

转载自blog.csdn.net/qq_41979513/article/details/100116544