201312-3 CCF試題簡析

1.試題描述
在橫軸上放了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

2.問題分析與實現代碼
第一種方法是使用暴力破解,算法複雜度O(n*n) 。先設第一個數爲最小值h,然後依次查找矩形比這個數小的,找到最小,計算面積,求出最大值,如此規律計算出所有可能出現的矩形面積結果,最後求出最大值。

#include<iostream>
int main()
{
 int n,i,j,h,s,max,a[1001];
 cin>>n;
 for(i=0;i<n;i++)
 cin>>a[i];
 max=0;
 //從第一個矩形開始,往右掃描,
 //若後面的矩形高度比第一個低,
 //則h爲較低的那個值,不斷髮生改變 
 for(i=0;i<n;i++)
 {
  h=a[i]; 
  for(j=i;j<n;j++)
  {
     if(a[j]<h) 
      h=a[j];
      s=h*(j-i+1);   //矩形面積=長X寬 
      if(s>max)
      max=s;
  } 
 }

第二種方法主要使用棧,時間複雜度O(n)。先找到一個逐步遞增的面積,即如果Hi<Hi+1,則最大面積是逐步遞增的。這個過程中,將這些Hi放入堆棧中,知道不滿足Hi<Hi+1,則最大面積是逐漸遞增的。這個過程中,將這些Hi放入堆棧中,知道不滿足Hi<Hi+1爲止。這個時候,最大的面積可能是最右邊Hi,由若干塊拼成,從中獲得一個最大的面積。出現面積非遞增式,則把堆棧中比當前高的直方圖彈出,重複上述過程。

#include "iostream"
#include "stack"
#include "vector"
#include "algorithm"
// 
using namespace std;
 
int getMaxArea(vector<int> &hist)
{
	
    stack<int> s;
 
    int i;
    int max=0;
    int max_area=0;
    int tp, area_with_top;
 
    while(i < hist.size())
    {
    	//若棧爲空或者棧頂元素小於hist[i],就入棧 
        if(s.empty() || hist[s.top()] <= hist[i])
            s.push(i++);
        else
        {
        	//否則,就計算此時的面積,與max_area進行比較 
            tp = s.top();
            s.pop();
            area_with_top = hist[tp] * (s.empty() ? i : i-s.top()-1);
             if(max_area<area_with_top){
             	max_area=area_with_top;
			 }
        }
    }
    while(!s.empty())
    {
        tp = s.top();
        s.pop();
        area_with_top = hist[tp] * (s.empty() ? i : i-s.top()-1);
        if(max_area<area_with_top){
             	max_area=area_with_top;
			 }
    }
 
    return max_area;
}
 
int main()
{
    int N;
    vector<int> vec;
    //輸入數據 
    cin >> N;
    for(int i=0;i<N;i++)
    {
        int val;
        cin >> val;
        vec.push_back(val);
    }
    //調用獲得最大面積函數 
    cout << getMaxArea(vec);
}

參考:https://www.bbsmax.com/A/QW5YDNPNJm/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章