描述
N位同學站成一排,音樂老師要請其中的(N-K)位同學出列,使得剩下的K位同學排成合唱隊形。
合唱隊形是指這樣的一種隊形:設K位同學從左到右依次編號為1,2…,K,他們的身高分別為T1,T2,…,TK, 則他們的身高滿足T1<...<Ti>Ti+1>…>TK(1<=i<=K)。
你的任務是,已知所有N位同學的身高,計算最少需要幾位同學出列,可以使得剩下的同學排成合唱隊形。
格式
輸入格式
輸入的第一行是一個整數N(2<=N<=100),表示同學的總數。第一行有n個整數,用空格分隔,第i個整數Ti(130<=Ti<=230)是第i位同學的身高(厘米)。
輸出格式
輸出包括一行,這一行只包含一個整數,就是最少需要幾位同學出列。
限制
每個測試點1s
來源
NOIP 2004
(轉自https://vijos.org/p/1098)
一看還真不好處理,至於高度從小到大再從大到小就先分開來看,先把從左邊開始的不下降子序列求出來,不如用個l數組
l[i]表示從到i這個點最長的不下降子序列的長度,再用個r數組,表示從右邊到i這個點最長不下降子序列的長度(注意是從右到左),然后再拼起來(l[i] + r[i]),減去一個人(第i個人算重了)就是i這個人當做k時最大可以選用的人的數量。
這樣的看得話就簡單多了,求2次最長不下降子序列,再for循環跑一趟就把最大可以選用的人數算出來。注意,l,r數組的初值是1(1個
人也可以排成這樣的序列)
Code
1 /* 2 * vijos.org 3 * Problem#1098 4 * Accepted 5 * Time:45ms 6 * Memory:556k 7 */ 8 #include<iostream> 9 #include<cstdio> 10 #include<cctype> 11 #include<cstring> 12 using namespace std; 13 template<typename T> 14 inline void readInteger(T& u){ 15 char x; 16 while(!isdigit((x = getchar()))); 17 for(u = x - '0';isdigit((x = getchar()));u = ((u << 3) + (u << 1) + x - '0')); 18 ungetc(x, stdin); 19 } 20 int n; 21 int *l,*r; 22 int *h; 23 void init(){ 24 readInteger(n); 25 h = new int[(const int)(n + 1)]; 26 l = new int[(const int)(n + 1)]; 27 r = new int[(const int)(n + 1)]; 28 for(int i = 1;i <= n;i++){ 29 readInteger(h[i]); 30 } 31 } 32 int result; 33 void solve(){ 34 for(int i = 1;i <= n; i++){ 35 l[i] = r[n - i + 1] = 1; 36 for(int j = 1;j < i; j++){ 37 if(h[i] > h[j] && l[i] <= l[j]) 38 l[i] = l[j] + 1; 39 if(h[n - i + 1] > h[n - j + 1] && r[n - i + 1] <= r[n - j + 1]) 40 r[n - i + 1] = r[n - j + 1] + 1; 41 } 42 } 43 for(int i = 1;i <= n;i++) 44 if(l[i] + r[i] > result) result = l[i] + r[i]; 45 } 46 int main(){ 47 init(); 48 solve(); 49 printf("%d",n - result + 1); 50 return 0; 51 }