HDU-1506 Largest Rectangle in a Histogram(单调栈,DP)

Largest Rectangle in a Histogram

HDU-1506 Largest Rectangle in a Histogram(单调栈,DP)_第1张图片

Sample Input

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

Sample Output

8
4000

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1506

题意:

求直方图中最大的矩形面积

思路:

有两种解法,个人感觉DP稍简单一点,单调栈不容易理解。

(一)DP

通过两次DP,找到每个的左侧和右侧比本身高的连续的位置,最后去找最大面积。第一遍,先从左到右,然后找每个数的左侧,记录下比本身高的连续的边界位置,为L。第一遍找到了全部的L。第二遍开始找每个位置的R,从右到左开始,找每个位置的右侧比本身高的连续的边界位置为R。这时每个位置的L,R都求出了。开始判断最大值。
第一遍找L。

		for(int i = 2; i <= n; i++) {
			int t = i;
			while(t > 1 && a[t-1] >= a[i]) {
				t = l[t-1];
			}
			l[i] = t;
		}

第二遍找R.

		for(int i = n-1; i >= 1; i--) {
			int t = i;
			while(t < n && a[t+1] >= a[i]) {
				t = r[t+1];
			}
			r[i] = t;
		}
代码:
#include
using namespace std;
const int maxn = 100000+10;
long long a[maxn];
long long l[maxn], r[maxn];
int main()
{
	int n;
	while(cin >> n && n) {
		for(int i = 1; i <= n; i++) {
			scanf("%lld", &a[i]);
		}
		l[1] = 1;
		r[n] = n;
		for(int i = 2; i <= n; i++) {
			int t = i;
			while(t > 1 && a[t-1] >= a[i]) {
				t = l[t-1];
			}
			l[i] = t;
		}
		for(int i = n-1; i >= 1; i--) {
			int t = i;
			while(t < n && a[t+1] >= a[i]) {
				t = r[t+1];
			}
			r[i] = t;
		}
		long long maxx = -1;
		for(int i = 1; i <= n; i++) {
			long long sum = (r[i] - l[i] + 1)*a[i];
			if(sum > maxx)
				maxx = sum;
		}
		cout << maxx << endl;
	}
	
	 
	return 0;
}

(二) 单调栈

单调栈的思想是:用一个栈来保存下标,遇到比栈中下标对应的值大的高度时,这时把这个下标进栈,保证栈中下标的高度为递增的(可以相等)。遇到比栈中下标对应值小的高度时,出栈并就计算面积(也就是栈顶元素的高度*(i-出栈后的栈顶-1),非空栈时),如果i == n时,且为空栈时这时面积为(height[栈顶] * i),和res比较,取最大值。
为了保证有结束状态,要在最后中压入一个0,height[n] = 0;
看例子比较清晰:
height=[2,1,5,6,2,3]

  1. 刚开始栈为空,压入下标0;当i=1时,不满足height[1] >= height[0],下标出栈,栈为空,计算面积res = height[0](1-0) = 2;
    HDU-1506 Largest Rectangle in a Histogram(单调栈,DP)_第2张图片
    2)高度1,5,6为依次递增的,所以对应下标依次压栈;此时栈元素有(1,2,3)。当i = 4时,不满足height[4] >= height[3],所以此时栈顶元素3出栈,计算此时面积res = height[3]
    (4-3)=6。
    HDU-1506 Largest Rectangle in a Histogram(单调栈,DP)_第3张图片
    3)当前栈为(1,2),栈顶为2,i=4,不满足height[4] >= height[2],所以栈顶2出栈,计算此时面积res=height[2]*(4-2)=10
    HDU-1506 Largest Rectangle in a Histogram(单调栈,DP)_第4张图片
    4)当前栈为(1),栈顶为1,i=4,满足height[4] >= height[1],所以i=4进栈,i++;栈为(1,4), i=5时,满足height[5] >= height[4],所以5进栈,栈为(1,4,5),i++;i=6,此时height[6]=0,不满足height[6] >= height[5],5出栈,计算面积res=(6-5)*height[5]=3;
    HDU-1506 Largest Rectangle in a Histogram(单调栈,DP)_第5张图片
    5)当前栈为(1,4),栈顶为4,i=6,不满足height[6] >= height[4],所以4出栈,计算面积res=(6-4)*height[4]=4;
    HDU-1506 Largest Rectangle in a Histogram(单调栈,DP)_第6张图片
    6)当前栈为(1),栈顶为1,i=6,不满足height[6] >= height[1],所以1出栈,此时为空栈,这次计算面积比较特殊res=height[1]n=16=6;
    HDU-1506 Largest Rectangle in a Histogram(单调栈,DP)_第7张图片
    参考博客:https://www.cnblogs.com/love-yh/p/7182920.html
代码:
#include
using namespace std;
const int maxn = 1000005;
long long height[maxn]; 
int main()
{
    int n;
    while(cin >> n && n) {
        for(int i = 0; i < n; i++){   
            cin>>height[i];
        }
        height[n] = 0;
        stack<int> s;
        long long maxx = 0; //这里一定要maxx = 0   否则错。。。。 
        long long sum = 0;
        for(int i = 0; i <= n; ++i) {
            if(s.empty() || (height[s.top()] <= height[i])) {
                s.push(i);
            }
            else {
                long long p = s.top();
                s.pop();
                if(s.empty()) 
					sum = height[p]*i;
				else
					sum = height[p]*(i-s.top()-1);
                
                if(sum >= maxx)
                    maxx = sum;
                --i;
            }
        }
        cout << maxx << endl;        
    }
    
    return 0;
} 



你可能感兴趣的:(DP)