• POJ-2559-Largest Rectangle in a Histogram(栈)


    题意: 有n个矩形,宽都是1,然后依次给你每个矩形的高。这n个矩形连在一起,现在让你规划一个矩形出来,使得这个矩形的面积最大

    思路: 其实这个题一眼看去很难想到用栈来做

    那么用栈怎么做呢?

    假设现在的数据是

    5

    1 2 3 4 5

    那我们栈内的元素为 1 2 3 4 5 

    那么area = max (area, s.top() * count);    count 是我们拿出栈内元素的个数

    为什么要这样写呢 我们来想 对于5这个东西 它只能被其他矩阵拿去用, 不能拿其他矩阵。  这样 area = 5 * 1

    然后pop()一下, 之后栈顶就是4个, 但我们想一下, 4这个东西, 是不是还可以从5里面拿一个4出来  这样 高为4的矩阵 就可以拿两个出来 则area = 4 *2

    之后依次

    area = 3 * 3

    area = 2 * 4

    area = 1 * 5

    那我们取一个最大的就好了 则 area = 8

    那现在问题来了 如果这个序列不是生序的呢

    n = 5

    2 4 4 1 5

    最开始 我们让2进栈, 因为后面的4比2大 所以这个2可以去贡献给4

    则 栈的元素是 2 4 4

    接下来是1

    1小于4  那么 我们就要把前面的元素全部更新成1 因为前面的2 4 4 都比1大

    然后记录一下 

    现在 对于 栈顶 4 我们就是 4 * 1 (虽然前面还有一个4 那如果这个4是5呢?)

    然后   4 * 2 弹栈

    然后   2 * 3 弹栈

    其实这样想 2 4 4 他是一个递增的对吧 对于后面的1来说 前面的3个 它最多只能拿高度为1的矩阵 所以说 前面这3个在用完之后 就没用了

    就算1后面有一个5 可以要连续的话 5也只能取1对吧~  画图直接画一下就好了

    那么现在栈里的元素是1 1 1  1 

    之后有一个5  5>s.top()

    入栈

    最后 栈的元素就是 1 1 1 1 5

    然后再去按照第一步递增的那种去处理一下。

    那我们再来看一下这个东西  里面都取了什么矩阵

    4 * 1  取中间那个矩阵

    4 * 2 取第二三个矩阵 每个高度是4

    2 * 3 取前三个   每个高度是2

    然后 5 * 1 取最后一个  每个高度是5

    1 * 2 取第 4  5个矩阵   每个高度是1

    1 * 3 取第 3 4 5矩阵  每个高度是1

    1 * 4 取第 2  3 4 5 矩阵   每个高度是1

    1 * 5 取全部矩阵 每个高度是1

    然后每次取记录最大的area就好了

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <stack>
    #include <cmath>
    using namespace std;
    const int maxn = 100100;
    stack<int> s;
    int a[maxn];
    int main(){
        int n;
        while(cin >> n && n){
            int ans = -1;
            while(!s.empty()){
                s.pop();
            }
            for(int i = 1; i <= n; i++){
                cin >> a[i];
            }
            for(int i = 1; i <= n; i++){
                if(s.empty() || s.top() <= a[i]){
                    s.push(a[i]);
                }
                else{
                    int num = 0;
                    while(!s.empty() && s.top() > a[i]){
                        num++;
                        ans = max(ans , s.top() * num);
                        s.pop();
                    }
                    num += 1;
                    while(num--){
                        s.push(a[i]);
                    }
                }
            }
            int num = 1;
            while(!s.empty()){
                ans = max(ans, s.top() * num);
                s.pop();
                num++;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }

    然后给出这里优化后的

    //建立一个单调递增栈,所有元素各进栈和出栈一次即可。每个元素出栈的时候更新最大的矩形面积。

    //设栈内的元素为一个二元组(x, y),x表示矩形的高度,y表示矩形的宽度。

    //若原始矩形高度分别为2,1,4,5,1,3,3

    //高度为2的元素进栈,当前栈为(2,1)

    //高度为1的元素准备进栈,但必须从栈顶开始删除高度大于或等于1的矩形,因为2已经不可能延续到当前矩形。删除(2,1)这个元素之后,更新最大矩形面积为2*1=2,然后把它的宽度1累加到当前高度为1的准备进栈的矩形,然后进栈,当前栈为(1,2)

    //高度为4的元素进栈,当前栈为(1,2) (4,1)

    //高度为5的元素进栈,当前栈为(1,2) (4,1) (5,1)

    //高度为1的元素准备进栈,删除(5,1)这个元素,更新最大矩形面积为5*1=5,把1累加到下一个元素,得到(4,2),删除(4,2),更新最大矩形面积为4*2=8,把2累加到下一个元素,得到(1,4),1*4=4<8,不必更新,删除(1,4),把4累加到当前准备进栈的元素然后进栈,当前栈为(1,5)

    //高度为3的元素进栈,当前栈为(1,5) (3,1)

    //高度为3的元素准备进栈,删除(3,1),不必更新,把1累加到当前准备进栈的元素然后进栈,当前栈为(1,5) (3,2)

    //把余下的元素逐个出栈,(3,2)出栈,不必更新,把2累加到下一个元素,当前栈为(1,7),(1,7)出栈,不必更新。栈空,结束。

    //最后的答案就是8。

    #include <cstdio>
    #include <utility>
    #include <queue>
    #include <stack>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef pair<long long , long long > pll;
    typedef long long ll;
    stack<pll > s;
    int n;
    int main(){
        while(scanf("%d", &n) && n){
            long long ans = 0;
            for(int i = 1; i <= n; i++){
                long long h, w;
                w = 0;
                scanf("%lld", &h);
                while(!s.empty() && s.top().first >= h){
                    ll temph = s.top().first;
                    ll tempw = s.top().second;
                    s.pop();
                    w += tempw;
                    ans = max(ans, temph * w);
                }
                s.push(make_pair(h, w + 1));
            }
            int temp = 0;
            while(!s.empty()){
                ans = max(ans, s.top().first * (temp + s.top().second));
                temp += s.top().second;
                s.pop();
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    64位win2008下IIS未开启32位支持导致DLL无法加载问题
    多控制器传递不同类型实体类到共用视图方案
    敏捷开发学习笔记——产品经理
    一些Razor语法
    敏捷开发学习笔记——用户故事与多职能团队
    UM九图
    Linq的分页
    easyUI datagrid 前端真分页
    C#项目的生成事件及批处理文件
    子类复制父类的值
  • 原文地址:https://www.cnblogs.com/weiyukang/p/9340874.html
Copyright © 2020-2023  润新知