hdu 1506 Largest Rectangle in a Histogram

来源:互联网 发布:中标麒麟用软件 编辑:程序博客网 时间:2024/05/14 09:42

题目链接:hdu 1506

题目大意:
给一些连续的,底固定为1,高度不等的矩形,这些矩形构成一个图形,求该图形包含的最大矩形面积。

例如:下面左边的图形,包含的最大矩形是右图的阴影面积

这里写图片描述

一开始,我是这么做的:

#include <cstdio>#include <climits>#include <cstring>const int maxn = 100000 + 10;typedef long long ll;ll h[maxn];int left[maxn];int right[maxn];const int inf = LLONG_MAX;int main(){    int n;    while(scanf("%d", &n) != EOF){        h[0] = inf;        for(int i = 1; i <= n; i++){            scanf("%d", &h[i]);            if(h[i] <= h[i-1]) left[i] = left[i-1] + 1;            else left[i] = 1;        }        h[n+1] = -1;        for(int i = n; i >= 1; i--){            if(h[i] <= h[i+1])                right[i] = right[i+1] + 1;            else right[i] = 1;        }        long long ans = 0;        for(int i = 1; i <= n; i++){            if(ans < (left[i]+right[i]-1)*h[i]){                ans = (left[i]+right[i]-1)*h[i];            }        }        printf("%lld\n", ans);    }    return 0;}

用h[i]表示第i个矩形的高度,left[i]和right[i]表示第i个矩形向左和向右的最大延伸长度,
核心代码是这两段递推式:

if(h[i] <= h[i-1]) left[i] = left[i-1] + 1;else left[i] = 1;
if(h[i] <= h[i+1]) right[i] = right[i+1] + 1;else right[i] = 1;

如果第i个矩形的高度小于第i-1个矩形的高度,left[i] = left[i-1]+1,
乍一看好像有点道理,但其实是错的,
比如这种情形:有3个矩形,高度分别是2,3,2.
left[2] = 1, h[3] < h[2],但left[3] != left[2] + 1。


以下是正确思路:

用left[i]和right[i]表示第i个矩形向左延伸的最小索引和向右延伸的最大索引,把left和right初始化为i。
如果h[left[i]-1] >= h[i],即第i个矩形可以向左延伸到第left[i] - 1个矩形。假设第left[i] - 1个矩形可以向左延伸到第k个矩形。
如果h[k] >= h[i],说明第i个矩形可以延伸到第k个矩形,left[i] = k,再求第k个矩形可以向左延伸的最小索引,再判断……
一直迭代下去直到不能再延伸。right数组同理。

#include <cstdio>#include <climits>const int maxn = 100000 + 10;typedef long long ll;int h[maxn];int left[maxn], right[maxn];const int inf = INT_MAX;int main(){    int n;    while(scanf("%d", &n), n){        for(int i = 1; i <= n; i++){            scanf("%d", &h[i]);            left[i] = right[i] = i;        }        ll ans = 0;        h[0] = h[n+1] = -1;        for(int i = 1; i <= n; i++){            while(h[left[i]-1] >= h[i])                left[i] = left[left[i]-1];        }        for(int i = n; i >= 1; i--){            while(h[right[i]+1] >= h[i])                right[i] = right[right[i]+1];        }        for(int i = 1; i <= n; i++){            if(ans < h[i]*1LL*(right[i] - left[i] + 1))                ans = h[i]*1LL*(right[i] - left[i] + 1);        }        printf("%lld\n", ans);    }    return 0;}
0 0
原创粉丝点击