POJ 2599 Largest Rectangle in a Histogram(DP&单调栈)

来源:互联网 发布:古剑奇谭网络版 知乎 编辑:程序博客网 时间:2024/06/16 15:11

题目可以戳这里

题意:连续输入n个紧挨着的宽度为1的矩形高度,求组成矩形的最大面积。

分析:
这题是个好题,迄今为止我已经见到过四种解法了,最容易想到的有dp与栈操作,此外还有单调队列和斜率优化的方式,综合时间空间与代码实现难度而言,这里我推荐dp大法。
此题最关键的地方便是能否想到用边界来划分区域,只要我们确保第i个矩形的左边界与右边界之间的矩形都高于第i个矩形,那么边界内最大面积必为height[i] * (right[i] - left[i] + 1)。而后比较每一个矩形的边界内最大面积即可。
难的地方在于如何得到每一个矩形的左右边界,我们可以先将每一个矩形的左右边界设为自身,并得到这样两个限制条件:
1.第i个矩形左边界(包括左边界)所在矩形必高于第i个矩形,第i个矩形的左边界所在矩形的左边界同时也是第i个矩形的左边界;
2.左边界大于1;
通过这两个条件,我们可以将左边界一直向左递推出去,便得到:

while(left[i] > 1 && height[left[i] - 1] >= height[i])    left[i] = left[left[i] - 1];

右边界同理。

代码:

//dp方法/** @author Novicer* language : C++/C*/#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;lint h[100005],lf[100005],rt[100005];int main(){    lint n;    while(scanf("%I64d",&n) == 1){        if(n == 0) break;        for(int i = 1 ; i <= n ; i++){            scanf("%I64d",&h[i]);            lf[i] = i;            rt[i] = i;            lint tmp = i;            while(h[lf[tmp] - 1] >= h[tmp] && lf[tmp] > 1)                lf[tmp] = lf[lf[tmp] - 1];        }        for(int i = n ; i >= 1 ; i--){            lint tmp = i;            while(h[rt[tmp] + 1] >= h[tmp] && rt[tmp] < n)                rt[tmp] = rt[rt[tmp] + 1];        }        lint ans = 0;        for(int i = 1 ; i <= n ; i++){            ans = max(ans , h[i] * (rt[i] - lf[i] + 1));        }        cout << ans << endl;    }    return 0;}//单调栈方法#include <stdio.h> #include <iostream>using namespace std;#define max(a,b) a > b ? a : b #define N 100005 int q[N]={-1},w[N];     //w记录的是从这个点开始,之前有几个高度大于等于此高度. int main() {     int n,h;     while(scanf("%d",&n),n)     {         int top = 0;         long long ans = 0;         for(int i=1;i<=n+1;i++)         {             if(i != n+1)                 scanf("%d",&h);             else                 h = 0;             if(h > q[top])                 q[++top] = h , w[top] = 1;             else             {                 long long cnt = 0;                 while(h <= q[top])                 {                     ans = max(ans ,(cnt+w[top])*q[top] );                     cnt += w[top--];                 }                 q[++top] = h;                 w[top] = cnt+1;             }         }         cout << ans << endl;    }     return 0; }
0 0
原创粉丝点击