NOIP 2004 T3 合唱队形(DP、最长上升/下降子序列)

 

 

链接:https://ac.nowcoder.com/acm/contest/1082/C
来源:牛客网

题目描述

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位同学的身高(厘米)。

输出描述:

输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。

示例1

输入

8
186 186 150 200 160 130 197 220

输出

 4

备注:

对于50%的数据,保证有n<=20;
对于全部的数据,保证有n<=100。

 

 

我们把这个序列分成两部分来看,那么左边的部分是求一个最长上升子序列,右边是求一个最长下降子序列。

那么我们就可以分别求一下整个序列的最长上升子序列和最长下降子序列,然后枚举中间点得到最多能留下来的人,然后就知道了答案。

 

代码如下:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <string>
 5 #include <math.h>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <queue>
 9 #include <set>
10 #include <stack>
11 #include <map>
12 #include <math.h>
13 const int INF=0x3f3f3f3f;
14 typedef long long LL;
15 const int mod=1e9+7;
16 const int maxn=1e5+10;
17 using namespace std;
18 
19 int n;
20 int A[105];
21 int L[105];//L[i]表示从1到i这个点最长的上升子序列的长度
22 int R[105];//R[i]表示从i到n这个点最长的下降子序列的长度即从n到i这个点最长的上升子序列的长度
23 
24 int main()
25 {
26     scanf("%d",&n);
27     for(int i=1;i<=n;i++)
28     {
29         scanf("%d",&A[i]);
30     }
31     for(int i=1;i<=n;i++)//正着求最长上升子序列 
32     {
33         L[i]=1;
34         for(int j=1;j<i;j++)
35         {
36             if(A[i]>A[j])
37                 L[i]=max(L[i],L[j]+1);
38         }
39     }
40     for(int i=n;i>=1;i--)//倒过来再求一遍最长上升子序列
41     {
42         R[i]=1;
43         for(int j=n;j>i;j--)
44         {
45             if(A[i]>A[j])
46                 R[i]=max(R[i],R[j]+1);
47         }
48     }
49     int MAX=0;
50     for(int i=1;i<=n;i++)//枚举中间点找最大值 
51     {
52         if(L[i]+R[i]-1>MAX)
53         {
54             MAX=L[i]+R[i]-1;
55         }
56     }
57     printf("%d\n",n-MAX);//减去最大值就是答案
58     return 0;
59 }

 

 

 

 

 

 

 

 

 

posted @ 2019-08-30 10:18  jiamian22  阅读(257)  评论(0编辑  收藏  举报