题目链接
题目描述
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
说明
- 对于50%的数据,保证有 n≤20 ;
- 对于全部的数据,保证有 n≤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;
}