题目链接

题目描述

N 位同学站成一排,音乐老师要请其中的( N−K )位同学出列,使得剩下的 KK 位同学排成合唱队形。

合唱队形是指这样的一种队形:设K位同学从左到右依次编号为 1,2,…,K ,他们的身高分别为T1,T2,…,TK , 则他们的身高满足T1<…Ti+1>…>TK(1≤i≤K) 。

你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

输入输出格式

  • 输入格式:

共二行。

第一行是一个整数N(2≤N≤100) ,表示同学的总数。

第二行有 n 个整数,用空格分隔,第 i 个整数 Ti(130≤Ti≤230) 是第 ii 位同学的身高(厘米)。

  • 输出格式:

一个整数,最少需要几位同学出列。

输入输出样例

输入样例#1:

8
186 186 150 200 160 130 197 220

输出样例#1:

4

说明

  1. 对于50%的数据,保证有 n \le 20n≤20 ;
  2. 对于全部的数据,保证有 n \le 100n≤100 。

解题思路

先用最长上升子序列求一遍,存在high数组里,再用最长下降子序列求一遍,存在low数组里。

重点:第x个人为队形中最高者时,队形的最大长度=x及其左侧的最长上升子序列长度+x及其右侧的最长下降子序列长度-1(x被算了两次)。这点理解了,题目就不难了。

注意求的是出列人数,所以最后勿忘用n减。这是我连交三次都20分的原因(ಥ﹏ಥ)

AC code:

#include<bits/stdc++.h>
const int MAXN=101;
using namespace std;
int n;
int a[MAXN];
int high[MAXN],low[MAXN];
int ans=0;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) //求整个序列中每个元素及其左侧的
{ //最长上升子序列长度
high[i]=1;
for(int j=1;j<i;j++)
if(a[i]>a[j])
high[i]=max(high[i],high[j]+1);
}
for(int i=n;i>0;i--) //求整个序列中每个元素及其右侧的
{ //最长下降子序列长度
low[i]=1;
for(int j=n;j>i;j--)
if(a[i]>a[j])
low[i]=max(low[i],low[j]+1);
}
for(int i=1;i<=n;i++) //找到最长队形
ans=max(ans,high[i]+low[i]-1);
printf("%d\n",n-ans); //用n减!!!
return 0;
}