问题描述 在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i(1 ≤ i ≤ n)个矩形的高度是hi。这n个矩形构成了一个直方图。例如,下图中六个矩形的高度就分别是3, 1, 6, 5, 2, 3。
请找出能放在给定直方图里面积最大的矩形,它的边要与坐标轴平行。对于上面给出的例子,最大矩形如下图所示的阴影部分,面积是10。
输入格式 第一行包含一个整数n,即矩形的数量(1 ≤ n ≤ 1000)。
第二行包含n 个整数h1, h2, … , hn,相邻的数之间由空格分隔。(1 ≤ hi ≤ 10000)。hi是第i个矩形的高度。 输出格式 输出一行,包含一个整数,即给定直方图内的最大矩形的面积。 样例输入 6
3 1 6 5 2 3 样例输出 10
思路:做这道题的原因是,我同学去科大参加 华为2016年实习生笔试,这道题恰好是第2题,算简单题了。好可惜,为啥子我没去报名,不然就过了一轮笔试了。
这道题求的是最大的矩形面积,每个小方块的面积都是1。假设现在前面有了n列的矩阵,当我在放第n+1列时,最大值只可能在以下几种情况中选择:
1.第n+1列的面积最大
2.之前的最大值也是加了这一列的最大值
3.第三种情况稍复杂一点,就是用一个高度为line的直线去切割,当line=1时,看一下line以下方格的最大值,注意这里遇到h[j]<line时停止,就比如,在图例中,当添加了第4列之后,当我用line=1去切,切了四路,最大值为4。用line=2去切,只能切两路,最大值为4。当循环到line=5时,切两路最大值为10,这是当前最大值
这道题我觉得应该算动态规划的例子。用f(i) 表示前i列的最大值,则f(i+1) = max( f(i), h[i+1], max temp(1<=line<=h[i+1]))
#include <iostream>
using namespace std;
#define MAX 1010
int main(){
int n,i,j,ans = 0;
cin>>n;
int h[MAX];
for(i=0;i<n;i++){
cin>>h[i];
}
int line = 0; //line是划线,平行于x轴的线
for(i=0;i<n;i++){
if(i == 0)
ans = h[0];
else{
ans = max(ans,h[i]); //先和自身高度求一个最值
line = 1;
while(line<=h[i]){
int num = 0; //表示以当前高度的line可以覆盖几路
for(j=i;j>=0;j--){
if(h[j]>=line)
num++;
else
break;
}
int temp = num * line;
ans = max(ans,temp);
line++;
}
}
}
cout<<ans<<endl;
return 0;
}
后来在思考的过程中,又想到一种方法。从第一列开始遍历,当固定i=0时,依次加入后面的列,组成的临时矩形高度是这几列最小的高度。遍历完一遍之后,记录i=0时的最值,之后再求出i=1,2,……(n-1)时的最值,比较求出最大值就OK
#include <iostream>
using namespace std;
#define MAX 1010
int main(){
int n,i,j,ans = 0;
cin>>n;
int h[MAX];
for(i=0;i<n;i++){
cin>>h[i];
}
for(i=0;i<n;i++){
int temp;
int low = h[i];
for(j=i;j<n;j++){
if(h[j]<low)
low = h[j];
temp = low * (j-i+1);
if(temp > ans)
ans = temp;
}
}
cout<<ans<<endl;
return 0;
}