2004年分区联赛提升组之三 合唱队形

合唱队形

Time Limit:1000MS Memory Limit:65536K
Total Submit:253 Accepted:111
ios

题目

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

Input

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

Output

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

Sample Input

8
186 186 150 200 160 130 197 220code

Sample Output

4xml

Hint

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

解题思路

题意是出列最少的人,使得剩下的人符合身高递增而后递减的规则。
能够先枚举中间最高的那我的,从1到最高者求最长不降低序列长度,
再从最高者到n求最长不上升序列长度,最后加起来并算出最少需出列几人。
最长不降低序列 a[i]<a[j] f[i]=max(f[i+1],f[i+2]······f[k])+1, k-1>=i>=1, i+1<=j<=k
最长不上升序列 a[i]>a[j] f[i]=max(f[i+1],f[i+2]······f[n])+1, n-1>=i>=k, i+1<=j<=nci

代码

#include<cstring>
#include<iostream>
using namespace std;
int n,m,a[10001],f[10001],c,ans=100000;
void in(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
}int DP(int k){
	int au=0;
	memset(f,0,sizeof(f));//必定要初始化
	f[k]=1;
	for(int i=k-1;i>0;i--){
		c=0;
		for(int j=i+1;j<=k;j++){
			if(a[i]<a[j]){
				if(f[j]>c){
					c=f[j];
				}
			}
		}f[i]=c+1;
	}for(int i=1;i<=n;i++){
		au=max(au,f[i]);
	}return k-au;//返回前i我的最小需出列数
}int DPd(int k){
	int au=0;
	memset(f,0,sizeof(f));//必定要初始化
	f[n]=1;
	for(int i=n-1;i>=k;i--){
		c=0;
		for(int j=i+1;j<=n;j++){
			if(a[i]>a[j]){
				if(f[j]>c){
					c=f[j];
				}
			}
		}f[i]=c+1;
	}for(int i=k;i<=n;i++){
		au=max(au,f[i]);
	}return n-k-au;//返回后i我的最小需出列数
}
void out(){
	cout<<ans;
}
int main(){
	in();
	for(int i=1;i<=n;i++){//枚举中间最高的人
		int x=DP(i),y=DPd(i);
		ans=min(x+y+1,ans);//最小出列数
	}out();
}