Codeforces Round #523 (Div. 2) B Views Matter
阿新 • • 發佈:2018-11-27
https://www.cnblogs.com/violet-acmer/p/10005351.html
這是一道貪心題麼????
題意:
某展覽館展覽一個物品,此物品有n堆,第 i 堆有a[ i ]個正方塊,問最多可以去除多少個正方塊,使得其俯檢視與右檢視的保持不變。
並且去除某正方塊a下方的正方塊時,是不會導致a方塊下降的(無重力)。
題解:
相關變數解釋:
1 int n,m; 2 ll sum;//所有的方塊 3 int a[maxn];//a[i] : 第i堆有a[i]個正方塊 4 int index;//來到第index堆物品 5 int maxHigh;//當前保留下來的正方塊的最大高度 6 int remain;//必須保留下的正方塊個數
單純的解釋,貌似,不太會,那就用個樣例解釋吧,哈哈哈。
例如:
1 Input 2 10 17 3 12 16 6 9 12 6 12 1 12 13 4 5 Output 6 83
首先,將a[ ]陣列按照從小到大的規則排序,排好序後,配圖如下:
大體思路是:
(1):從第一堆物品開始遍歷,定義變數h=a[ i ]-maxHigh,根據maxHigh的定義可知,在第一堆物品之前,是沒有方塊的,所以,初始化maxHigh=0,那麼h代表的就是
當前堆需要保留的最多的方塊數,定義變數len=n-index+1,index表示的是當前來到第index堆,那麼len就表示在這之後還有多少堆。
(2):判斷是否可以組成h*h的大正方形,也就是判斷len是否大於等於h:
①如果可以,例如圖片中的紅方框,如果可以,那麼h*h的正方形上的對角線上的方塊是一定要保留的,且是當前正方形需要保留的最少的方塊數。
②反之,len*len的正方形最少需要保留的方塊個數也是其對角線的方塊個數。
(3):當index > n 時,判斷maxHigh是否達到了最大高度a[n],如果沒有,還需額外保留a[n]-maxHigh個正方塊。
具體細節看程式碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 #define ll long long 6 const int maxn=1e5+10; 7 8 int n,m; 9 ll sum; 10 int a[maxn]; 11 12 ll Solve() 13 { 14 sort(a+1,a+n+1); 15 if(n == 1) 16 return 0; 17 ll remain=0; 18 int index=1,maxHigh=0; 19 while(index <= n) 20 { 21 int h=a[index]-maxHigh; 22 int len=n-index+1; 23 if(len >= h)//可以形成h*h的正方形 24 { 25 //注意需要特判h == 0的情況 26 remain += (h == 0 ? 1:h);//需要保留的最少的方塊數為h個 27 index += (h == 0 ? 1:h);//[index,index+h]已經保留過正方塊了,直接來到index+h堆 28 maxHigh += h;//更新前index堆達到的最大高度 29 } 30 else//可以形成len*len的正方形 31 { 32 remain += len; 33 index += len; 34 maxHigh += len; 35 } 36 } 37 remain += (a[n]-maxHigh);//步驟(3) 38 return sum-remain; 39 } 40 41 int main() 42 { 43 cin>>n>>m; 44 for(int i=1;i <= n;++i) 45 cin>>a[i],sum += a[i]; 46 cout<<Solve(); 47 }View Code