CCF-CSP 最大的矩形


問題描述
  在橫軸上放了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
 
思路:第一次看見這題的想法就是:
  1、先輸入數據,存入一個數組里
  2、遍歷數組中的每個元素,並找出當前數組元素左邊和右邊第一個小於當前數組元素的數
  3、由剛才得到的數組元素的下標,計算這段距離中有多少個矩形,
  4、當前元素 * 距離 = temp
  5、比較最終答案和temp,如果temp大於最終答案ans,那么ans = temp,否則繼續
但是提交之后發現會超時,每次反復的運算大大增加了時間復雜度,所以筆者從別人那里借鑒到一種方法:
  這種方法的大體思路是這樣的,輸入數據之后,遍歷每個數據,對於其中的每一個數據a[i], 從下表i到n-1之間,找到最小的數a[j],用它乘以i到j之間矩形的個數,如果得到的答案大於最終要輸出的答案,那么就把這個答案賦值給最終答案。
  說的比較籠統,一會再深入講解,先看看代碼:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<vector>
 4 #include<string>
 5 #include<cstring>
 6 using namespace std;
 7 const int N = 1003;
 8 int a[N];
 9 
10 int main(){
11     int n;
12     while(cin>>n){
13         for(int i =0  ;i < n;++i){          //輸入數據
14             cin>>a[i];
15         }
16         int ans = -1;                  //先設置最終答案ans為-1
17         for(int i = 0 ; i< n;++i){          //對於每個元素a[i]
18             int low = a[i];              //當前最小值low設置為a[i]
19             for(int j =  i ; j < n;++j){       //對於i后面的每個元素
20                 if(low > a[j])            //如果a[j] 比 當前設置的最小值還要小,那么最小值設置為a[j]
21                     low = a[j];
22                 int temp = (j - i + 1) * low;      //設置標記變量temp 為這段區間中的總和
23                 if(temp > ans)              
24                     ans = temp;
25             }
26         }
27         cout<<ans<<endl;
28     }
29 return 0;
30 }

我想還有許多人對二層循環那里不明白,其實筆者剛開始也不太明白,下面就來講解一下這里吧、、、

有一個問題,就是總是向右邊遍歷,那么左邊的數據怎么算?

其實,在不斷向右邊遍歷的過程中,我們如果把下標 i  看成后面每個數的左邊界就好了、、、

假如 i 現在為0,那么右邊的每個數的左邊界都是 0,並且按照代碼中寫的,不斷找到i 到j之間的最小值,那么 0 到 i 之間的最小值的最終結果是不是就是n * 最小值呢

如果還不明白,還可以這么想,假如就三個數據,a1,a2,a3, 假如a1 比a2 小的前提下,

(1)a3 大於 a2 並且大於 a1 那么對於a3來說,最大值就是a3

(2)a3小於a2 並且大於a1 ,那么對於a3來說,最大值就是a3 * 2

、、、、、

所以從前向后遍歷的過程,其實就是不斷對於下標為i后面的某個元素j的左方向遍歷過程、、、

大家懂了嗎,如果還有問題,希望大家能提出來,筆者深知能力有限,但是能幫助大家的還是會盡力的、、


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM