给一个柱状统计图,各个小矩形宽度相等,高度不一,每一个矩形是由几个相邻柱状条条组成,矩形的高度为最短的那根条条,求所有组合中最大的矩形面积,假设柱状统计图是放在数组里的,数组记录的是每个条条的高度。
http://zhangzhibiao02005.blog.163.com/blog/static/3736782020118433623459/
在直方图中,一个长方形由其左边界和右边界决定,其最大可能的高度由两者中的最小者决定。记 R(i,j) 为由第 i 个直方柱为左边界,第 j 个直方柱确定的面积最大的长方形。如果 R(i,j) 的面积最大,那么,第 i 个直方柱比它的前一个直方柱(如果存在的话),即第 i-1 个直方柱要高,而 第 j 个直方柱的高度也比第 j+1 个的要高,否则,由 R(i,j+1) 或 R(i-1,j) 的面积比 R(i,j) 还要大,这违背了 R(i,j) 的最优性。根据这个观察,我们从第1个直方柱开始,寻找第一个 i, 使得直方柱 i 的高度比 i+1 的大,则 i 是一个可能的右边界,而 i 之前的每一根直方柱都是可能是左边界(因为 i 是第一个比 i + 1 高的直方柱,所以,在 i 之前的是一个上升的直方柱序列,每一根都比前一根要高)。这时,我们计算前面所有可能的长方形的面积,并跟当前已知的最大值进行比较,并更新当前已知的最大值(如有必要的话)。然后,我们继续向前搜索第二个这样的 i 。重复这个过程,直到最后一根直方柱。
设R(i, j)是最大矩阵的左右边界,那么height[j] > height[j +1], height[i] > height[i-1]
所以一旦遇到高度小于当前栈顶元素时,就有可能有最大矩阵,这时候就要从栈中不断的弹出
int maxRec(int a[], int n) {
if (n == 0)
return 0;
stack<Node> sk;
int rst = 0;
sk.push(Node(0,a[0]));
for(int i = 1; i < n; ++i ) {
if(a[i] >= sk.top().height)
sk.push(Node(i,a[i]));
else {
Node last = sk.top();
while (!sk.empty() && sk.top().height > a[i])
{
Node t = sk.top();
sk.pop();
int rec = (last.index - t.index + 1) * t.height;
if (rst < rec)
rst = rec;
}
sk.push(Node(i,a[i]));
}
}
Node last = sk.top();
while (!sk.empty()) {
Node t = sk.top();
sk.pop();
int rec = (last.index - t.index + 1) * t.height;
if(rst < rec)
rst = rec;
}
return rst;
}
对于这一题:
有一个 m x n 的矩阵,元素为 0 或 1。一个子矩阵,如果它所有的元素都是 0, 或者都是 1,则称其为一个 0-聚类 或 1-聚类,统称聚类(Cluster)。请找出最大的聚类(元素最多的聚类)。(问题来源:某面试题)
可以用之前所讲的dp做:http://blog.youkuaiyun.com/sunmenggmail/article/details/7709004
也可以用直方图最大矩阵做。
一行一行处理,每一行把0的高度看做是直方图,然后求出这一行的最大矩阵