HDU1506 POJ2559 Largest Rectangle in a Histogram【单调堆栈】

Largest Rectangle in a Histogram

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 31315 Accepted Submission(s): 10156

Problem Description
A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the heights 2, 1, 4, 5, 1, 3, 3, measured in units where 1 is the width of the rectangles:
在这里插入图片描述
Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.

Input
The input contains several test cases. Each test case describes a histogram and starts with an integer n, denoting the number of rectangles it is composed of. You may assume that 1 <= n <= 100000. Then follow n integers h1, …, hn, where 0 <= hi <= 1000000000. These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is 1. A zero follows the input for the last test case.

Output
For each test case output on a single line the area of the largest rectangle in the specified histogram. Remember that this rectangle must be aligned at the common base line.

Sample Input
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0

Sample Output
8
4000

Source
University of Ulm Local Contest 2003

问题链接HDU1506 POJ2559 Largest Rectangle in a Histogram
问题简述:计算直方图最大面积问题。
问题分析
    解决这个问题,一种是用暴力法(枚举法)来解决,任何一个矩形必然始于第i个直方图,终止于第j块直方图(i<=j),从所有这些面积中找出最大矩形面积即可;另外一种办法是对这n个数只看一遍,就算出最大矩形面积,其计算复杂度为O(n),相比较而言,算法要复杂一些,需要付出一些空间的代价;再一种方法是采用DP的做法。
    后一种方法的基本思想是先找到一个逐步递增的面积,即如果Hi<Hi+1则最大面积是逐步递增的。这个过程中,将这些Hi放入堆栈中,直到不满足Hi<Hi+1为止。这个时候,最大的面积可能是最右边是Hi,由若干块(也可能只有1块)拼成的,从中获得一个最大的面积。出现面积非递增时,则把堆栈中比当前高的直方图弹出,重复上述过程,需要说明的是这不影响高的直方图与其右边连成一片。还有一点就是,所有的直方图的高度Hi>=1,这是一个前提,如果有的直方图高度为0,则这个算法需要另外设计。
程序说明:(略)
参考链接CCF201312-3 最大的矩形(100分)
题记:(略)

AC的C++语言程序(DP)如下:

/* HDU1506 POJ2559 Largest Rectangle in a Histogram */

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int INF = 0x7F7F7F7F;
const int N = 100000 + 2;
int l[N], r[N];
long long h[N];

int main()
{
    int n;
    while(~scanf("%d", &n) && n) {
        memset(h, 0, sizeof(h));
        for(int i = 1; i <= n; i++) {
            scanf("%lld", &h[i]);
            l[i] = r[i] = i;
        }

        l[0] = 1;
        r[n + 1] = n;
        h[0] = -1;
        h[n + 1] = -1;
        for(int i = 1; i <= n; i++)
            while(h[l[i] - 1] >= h[i]) l[i] = l[l[i] - 1];      // 找位置i的左边界
        for(int i = n; i >= 1; i--)
            while(h[r[i] + 1] >= h[i]) r[i] = r[r[i] + 1];      // 找位置i的右边界

        long long maxArea = -INF;
        for(int i = 1; i <= n; i++)
            maxArea = max(maxArea, h[i] * (r[i] - l[i] + 1));

        printf("%lld\n", maxArea);
    }

    return 0;
}

AC的C++语言程序如下:

/* POJ2559 HDU1506 Largest Rectangle in a Histogram */
 
#include <iostream>
#include <cstdio>
#include <stack>
 
using namespace std;
 
const int MAXN = 100000;
 
long long h[MAXN+1];
 
int main()
{
    int n, temp;
    long long ans, area;
 
    while(scanf("%d", &n) != EOF && n) {
        // 输入数据
        for(int i=0; i<n; i++)
            scanf("%lld", &h[i]);
        h[n] = 0;
 
        // 计算最大矩形面积
        ans = 0;
        stack<int> s;
        for(int i=0; i<=n; i++) {
            if (s.empty() || h[s.top()] < h[i])
                s.push(i);
            else {
                temp = s.top();
                s.pop();            //弹出
                area = h[temp] * (s.empty() ? i : i - s.top() - 1);
                if (area > ans)
                    ans = area;
                --i;
            }
        }
 
        // 输出结果
        printf("%lld\n", ans);
    }
 
    return 0;
}

TLE的C++语言程序如下:

/* POJ2559 HDU1506 Largest Rectangle in a Histogram */
 
#include <iostream>
#include <cstdio>
 
using namespace std;
 
const int MAXN = 100000;
 
long long h[MAXN];
 
int main()
{
    int n;
    long long ans, height, area;
 
    while(scanf("%d", &n) != EOF && n) {
        // 输入数据
        for(int i=0; i<n; i++)
            scanf("%lld", &h[i]);
 
        // 计算最大矩形面积:暴力法(枚举法)
        ans = 0;
        for(int i=0; i<n; i++) {
            height = h[i];
            for(int j=i; j<n; j++) {
                if(h[j] < height)
                    height = h[j];
                area = (j - i + 1) * height;
                if(area > ans)
                    ans = area;
            }
        }
 
        // 输出结果
        printf("%lld\n", ans);
    }
 
    return 0;
}
发布了2289 篇原创文章 · 获赞 2373 · 访问量 265万+

猜你喜欢

转载自blog.csdn.net/tigerisland45/article/details/105440799