题目链接:http://acm.ocrosoft.com/problem.php?id=2816
题目描述
NN位同学站成一排,音乐老师要请其中的(N−K)(N−K)位同学出列,使得剩下的KK位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,…,K1,2,…,K,他们的身高分别为T1,T2,…,TKT1,T2,…,TK,则他们的身高满足T1<T2<…<Ti,Ti>Ti+1>…>TK(1≤i≤K)T1<T2<…<Ti,Ti>Ti+1>…>TK(1≤i≤K)。
你的任务是,已知所有NN位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入
输入的第一行是一个整数N(2≤N≤100)N(2≤N≤100)
,表示同学的总数。第二行有nn
个整数,用空格分隔,第ii
个整数Ti(130≤Ti≤230)Ti(130≤Ti≤230)
是第ii
位同学的身高(厘米)。
输出
输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
样例输入
8
186 186 150 200 160 130 197 220
样例输出
4
提示
对于50%的数据,保证有n ≤ 20;对于全部的数据,保证有n≤100。
#include<bits/stdc++.h>
using namespace std;
//f[i][0]表示1-n的顺序第i个人为结尾的最长上升子序列
//f[i][1]表示n-1的顺序第i个人为结尾的最长上升子序列
int n,a[105],f[105][2],ans;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
a[0]=0;
//从1到n求最长上升序列
for(int i=1;i<=n;i++){
for(int j=0;j<i;j++){
if(a[i]>a[j]){
//有取和不取两种状态
f[i][0]=max(f[i][0],f[j][0]+1);
}
}
}
a[n+1]=0;
//从n到1求最长上升序列
for(int i=n;i;i--){
for(int j=n+1;j>i;j--){
if(a[i]>a[j]){
f[i][1]=max(f[i][1],f[j][1]+1);
}
}
}
//枚举Ti,从1到Ti的最长升+从TK到Ti的最长升-1(因为Ti被加了两次)
for(int i=1;i<=n;i++) {
ans=max(f[i][0]+f[i][1]-1,ans);
}
cout<<n-ans<<endl;
return 0;
}