【NOIP】合唱队形

【NOIP】合唱队形

题目

题目描述

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

合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,…,K,他们的身高分别为T_1,T_2,…,T_KT
1​ ,T 2​ ,…,T ​ , 则他们的身高满足T_1<…T_{i+1}>…>T_K​ (1≤i≤K)。

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

输入格式
共二行。

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

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

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

输入输出样例

输入 #1 复制
8
186 186 150 200 160 130 197 220
输出 #1 复制
4

说明/提示

对于50%的数据,保证有0n≤20;

对于全部的数据,保证有0n≤100。

分析

这是一道水题, 题目说的是 求出先上升后递减的子序列,要求到达最长。

如图一样,我们求出在每个点 的,先上升到这个点,再下降 的子序。 求出所有点的情况,
然后比较哪个点的长度最长就ok

**注意:**写代码时 所枚举的点,在求子序时 会经过该点两次,所以长度要减掉1;
(这里写的是o(n^2)写法, o(nlogn)写法和导弹拦截那道相似。导弹拦截 传送
【NOIP】合唱队形_第1张图片

代码

这是o(n^2)写法,还有o(nlogn)写法,和导弹拦截那道相似

#include

using namespace std;

int n;
int a[105];
int dp1[105],dp2[105];

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	
	for(int i=1;i<=n;i++){
		dp1[i] = 1;
		for(int j=1;j<i;j++){
			if(a[i] > a[j]){
				dp1[i] = max(dp1[i],dp1[j]+1);
			}
			
		}
	}	
	for(int i=n;i>=1;i--){
		dp2[i] = 1;
		for(int j=i+1;j<=n;j++){
			if(a[i] > a[j]){
				dp2[i] = max(dp2[i],dp2[j]+1);
			}	
		}
	}
	int ans =0;
	for(int i=1;i<=n;i++){
		ans = max(ans,dp1[i]+dp2[i]-1);
	}
	cout<<n-ans;	
	
	return 0;
}

你可能感兴趣的:(NOIP,#,线性动态规划)