最大的矩形 (201312-3)

116 篇文章 2 订阅
35 篇文章 0 订阅

问题描述
  在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i(1 ≤ i ≤ n)个矩形的高度是h i。这n个矩形构成了一个直方图。例如,下图中六个矩形的高度就分别是3, 1, 6, 5, 2, 3。



  请找出能放在给定直方图里面积最大的矩形,它的边要与坐标轴平行。对于上面给出的例子,最大矩形如下图所示的阴影部分,面积是10。
输入格式
  第一行包含一个整数n,即矩形的数量(1 ≤ n ≤ 1000)。
  第二行包含n 个整数h 1, h 2, … , h n,相邻的数之间由空格分隔。(1 ≤ h i ≤ 10000)。h i是第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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值