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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章