九度oj 题目1131:合唱队形

题目描述:

N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,
则他们的身高满足T1 < T2 < … < Ti , Ti > Ti+1 > … > TK (1 <= i <= K)。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

输入:

输入的第一行是一个整数N(2 <= N <= 100),表示同学的总数。
第一行有n个整数,用空格分隔,第i个整数Ti(130 <= Ti <= 230)是第i位同学的身高(厘米)。

输出:

可能包括多组测试数据,对于每组数据,
输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。

样例输入:
8
186 186 150 200 160 130 197 220
样例输出:
4
开始看题觉得好难,后来在沙发上躺着一拍脑门,这不就是求最长上升子序列吗,代码如下:
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #define MAX 102
 5 
 6 int high[MAX];
 7 int left[MAX];
 8 int right[MAX];
 9 //             186 186 150 200 160 130 197 220
10 // left        0    0   0   1   1   0   2   3
11 // right    2    2   1   2   1   0   0   0
12 //             5     5     7   4     5   7   5   4
13 int main(int argc, char const *argv[])
14 {
15     int n;
16     while(scanf("%d",&n) != EOF) {
17         for(int i = 0; i < n; i++) {
18             scanf("%d",&high[i]);
19             left[i] = 0;
20             right[i] = 0;
21         }
22         for(int i = 0; i < n; i++) {
23             int max = -1;
24             bool isMin = true;
25             for(int j = i -1; j >= 0; j--) {
26                 if(high[j] < high[i] && max < left[j]) {
27                     max = left[j];
28                     isMin = false;
29                 }
30             }
31             if(!isMin) {
32                 left[i] = max + 1;
33             }
34             
35         }
36 
37         for(int i = n-1; i >= 0; i--) {
38             int max = -1;
39             bool isMin = true;
40             for(int j = i + 1; j < n; j++) {
41                 if(high[j] < high[i] && max < right[j]) {
42                     max = right[j];
43                     isMin = false;
44                 }
45             }
46             if(!isMin) {
47                 right[i] = max + 1;
48             }
49         }
50 
51         int ans = n;
52         for(int i = 0; i < n; i++) {
53             int temp = n - (left[i] + right[i] + 1);
54             if(ans > temp) {
55                 ans = temp;
56             }
57         }
58         printf("%d
", ans);
59     }    
60     return 0;
61 }

 注释:以每一个人作为考虑对象,左值是到他的最长上升子序列,右值是他的最长下降子序列,两序列相加再减1(减不减和下标的定义有关)即为满足合唱队形的人数

原文地址:https://www.cnblogs.com/jasonJie/p/5712817.html