• 动态规划-直方图最大长方形


    /*
    1017: C03-单调栈算法-最大长方形
    时间限制: 1 Sec 内存限制: 128 MB 提交: 17 解决: 10 [提交] [状态] [讨论版] [命题人:外部导入] 题目描述 给你一个直方图,告诉你各个条形矩形的高度,求基线对齐构成的矩形中面积最大的矩形的面积。对于每一个矩形,面积 = h[i]*(j-k+1),其中j,k是左右边界,h[i]是矩形 的高。并且对于j <= x <= k,h[i] <= h[x]。 代码提交链接 输入 输入包含几个测试用例。每个测试用例描述一个直方图,并以整数n开始,表示它由多少个矩形组成。你可以假设1 <= n <= 100000。然后按照n个整数h1,…, hn,其中0 <= hi <= 1000000000。这些数字表示直方图中从左到右排列的矩形的高度。每个矩形的宽度是1。0紧跟最后一个测试用例的输入。 输出 对于单个行上的每个测试用例输出,指定直方图中最大矩形的面积。记住,这个矩形必须与公共基线对齐。 样例输入 7 2 1 4 5 1 3 3 4 1000 1000 1000 1000 0 样例输出 8 4000 提示 我们可以用一个单调栈由低到高来存储它的高度,并用数组对每个高度记录一下它前面(包括它自己)一共有多少个比它高的,可以看做它的左宽。 按顺序考虑每个高度h,如果h大于栈顶元素,则入栈,此时它大于左面全部的元素,并且将它的宽度初始为1。 否则,将栈内元素出栈,直到满足上面的条件。出栈时,我们要将出栈元素对之后问题的影响全部考虑进行处理,才能保证做法的正确性。 对于每个高度,它的作用无非两个:1、以自己作高,向外扩展 2、以别人作高,自己被扩展 由于我们数组中已经记录了某个高度的左宽,所以我们只需要考虑它能不能向右扩展,如果能,能扩展多少? 首先,对于第一个出栈的元素来说,它的右宽一定是0。 然而对于第二个,它的右边有刚才出栈的元素,而且刚才出栈元素的总宽中所涉及的元素一定可以被自己扩展,所以自己的右宽为刚才出栈元素的总宽。 同理可知,第三个出栈元素的右宽为第二个出栈元素的总宽。依次类推。 而当h大于栈顶元素时,h的左宽应该是上次出栈元素的总宽+1(自己),然后入栈。 最后时,将所有元素出栈,即可将所有情况考虑。 来源/分类 C03-栈 [提交] [状态]
    */ #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<string> #include<cstring> #include<stack> using namespace std; const int Max_N=100008; struct Elem{ int id;//向左扩展最远的下标 long long height;//当前节点高度 Elem(){} //在其他的地方要定义一个Elem类型的变量的时候一定要加 Elem(int _id,long long _height):id(_id),height(_height){} }; int N; long long x[Max_N]; long long Ans(){ int i,L_id; long long ans=0; Elem e; stack<Elem> stk; for(i=0;i<=N;i++) { L_id=i; while(!stk.empty()&&stk.top().height>x[i]){ ans=max(ans,(long long)(i-stk.top().id)*stk.top().height); L_id=stk.top().id; stk.pop(); } //由于上面修改了L_id,这里相当于每次加入一个长度为(i-L_id)的长方形 //这里枚举一遍找一个最大值就可以了 stk.push(Elem(L_id,x[i])); } return ans; } int main() { int i; while(cin>>N&&N) { for(int i=0;i<N;i++) scanf("%lld",&x[i]); x[N]=-1; cout<<Ans()<<endl; } return 0; } /************************************************************** Problem: 1105 User: Blingo Language: C++ Result: 正确 Time:36 ms Memory:2880 kb ****************************************************************/

    1105: B10-动态规划:直方图最大长方形

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 8  解决: 5
    [提交] [状态] [讨论版] [命题人:外部导入]

    题目描述

    给你一个直方图,告诉你各个条形矩形的高度,求基线对齐构成的矩形中面积最大的矩形的面积。对于每一个矩形,面积 = h[i]*(j-k+1),其中j,k是左右边界,h[i]是矩形

    的高。并且对于j <= x <= k,h[i] <= h[x]。



    输入

    输入包含几个测试用例。每个测试用例描述一个直方图,并以整数n开始,表示它由多少个矩形组成。你可以假设1 <= n <= 100000。然后按照n个整数h1,…, hn,其中0 <= hi <= 1000000000。这些数字表示直方图中从左到右排列的矩形的高度。每个矩形的宽度是1。0紧跟最后一个测试用例的输入。

    输出

    对于单个行上的每个测试用例输出,指定直方图中最大矩形的面积。记住,这个矩形必须与公共基线对齐。

    样例输入

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

    样例输出

    8
    4000

    提示


    我们可以用一个单调栈由低到高来存储它的高度,并用数组对每个高度记录一下它前面(包括它自己)一共有多少个比它高的,可以看做它的左宽。
    按顺序考虑每个高度h,如果h大于栈顶元素,则入栈,此时它大于左面全部的元素,并且将它的宽度初始为1。
    否则,将栈内元素出栈,直到满足上面的条件。出栈时,我们要将出栈元素对之后问题的影响全部考虑进行处理,才能保证做法的正确性。
    对于每个高度,它的作用无非两个:1、以自己作高,向外扩展        2、以别人作高,自己被扩展
    由于我们数组中已经记录了某个高度的左宽,所以我们只需要考虑它能不能向右扩展,如果能,能扩展多少?
    首先,对于第一个出栈的元素来说,它的右宽一定是0。
    然而对于第二个,它的右边有刚才出栈的元素,而且刚才出栈元素的总宽中所涉及的元素一定可以被自己扩展,所以自己的右宽为刚才出栈元素的总宽。
    同理可知,第三个出栈元素的右宽为第二个出栈元素的总宽。依次类推。
    而当h大于栈顶元素时,h的左宽应该是上次出栈元素的总宽+1(自己),然后入栈。
    最后时,将所有元素出栈,即可将所有情况考虑。


    来源/分类

    [提交] [状态]
  • 相关阅读:
    外校培训前三节课知识集合纲要(我才不会告诉你我前两节只是单纯的忘了)
    floyd算法----牛栏
    bfs开始--马的遍历
    (DP 线性DP 递推) leetcode 64. Minimum Path Sum
    (DP 线性DP 递推) leetcode 63. Unique Paths II
    (DP 线性DP 递推) leetcode 62. Unique Paths
    (DP 背包) leetcode 198. House Robber
    (贪心 复习) leetcode 1007. Minimum Domino Rotations For Equal Row
    (贪心) leetcode 452. Minimum Number of Arrows to Burst Balloons
    (字符串 栈) leetcode 921. Minimum Add to Make Parentheses Valid
  • 原文地址:https://www.cnblogs.com/Tidoblogs/p/11173398.html
Copyright © 2020-2023  润新知