问题描述:
在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i(1<=i<=n)个矩形的高度是hi,这n个矩形构成了一个直方图,例如,下图中六个矩形的高度就分别是3,1,6,5,2,3
请找出能放在给定直方图里面积最大的矩形,他的边要与坐标轴平行。
输入格式:第一行包含一个整数n,即矩形的数量(1<=n<=100)
第二行包含n个整数h1,h2,…hn,相邻的数之间由空格分隔(1<=hi<=10000)hi是第i个矩形的高度
输出格式:输出一行,即直方图内最大矩形的面积
样例输入
6
3 1 6 5 2 3
样例输出
10
题解:就是在这个形状中找出面积最大的矩形,对于上图,里面最大的面积就是第三列和第四列,宽为2,高为5,面积是10,
#include "iostream"
#include "stack"
using namespace std;
const int N=1000;
int h[N+1];
int main(){
int n,ans=0,area,temp; //最终返回的面积是area
//输入数据
cin>>n;
for(int i=0;i<n;i++){
cin>>h[i];
}
h[n]=0;
stack<int> s;
for(int i=0;i<=n;i++){
if(s.empty()||h[s.top()]<h[i]) // 如果栈顶元素小于后面一个柱形 则压入栈
s.push(i);
else{
temp=s.top();
s.pop();
area=h[temp]*(s.empty()?i:i-s.top()-1); // 如果s是空的则乘以i 不是空则乘以i-s.top()-1
if(area>ans)
ans=area;
i--;
}
}
cout<<ans<<endl;
return 0;
}
在这个里面 if()执行的是能够入栈的元素都是当前高度最高的那一列的横坐标,如果后面的纵坐标比当前的低,则执行else中temp=s.top(); 去除栈顶元素后,此时栈顶元素是比前一个取出的栈顶元素小的那一列的横坐标(),h[temp]*(s.empty()?i:i-s.top()-1)中h[temp]是最大的那一个横坐标的高,如果栈中空时,则乘以i,不为空则乘以i-s.top()-1,这里应该时i - (s.top()+1),因为从数组从0开始计算,
其实i–;的作用就是为了一直把栈顶pop()直到 小于等于h[i],这样之前大于h[i]的横坐标将全部被pop(),如果栈中每一个元素都比h[i]要大,那么这个i肯定是刚刚才入栈的元素且栈中只有他一个元素。这样先把自己pop()出来,再乘以i,即图的横坐标最大值n
所以前面定义数组时候定义成h[N+1],而且再for循环中i的循环条件是i<=n