题目描述
\(N\)位同学站成一排,音乐老师要请其中的\((N-K)\)位同学出列,使得剩下的\(K\)位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为\(1,2,…,K\),他们的身高分别为\(T_1,T_2,…,T_K\), 则他们的身高满足\(T_1<...>…>T_K(1 \le i \le K)\)
你的任务是,已知所有\(N\)位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入输出格式
输入格式:
共二行。
第一行是一个整数\(N(2 \le N \le 100)\),表示同学的总数。
第二行有nn个整数,用空格分隔,第\(i\)个整数\(T_i(130 \le T_i \le 230)\)是第\(i\)位同学的身高(厘米)。
输出格式:
一个整数,最少需要几位同学出列。
输入输出样例
输入样例#1:
8
186 186 150 200 160 130 197 220
输出样例#1:
4
说明
对于\(50%\)的数据,保证有\(n \le 20n≤20\);
对于全部的数据,保证有\(n \le 100n≤100\)。
思路
此题是动态规划的基础题之一,我太lj了,最后想不出来怎么处理来得到最大值qwq
和日常生活中照照片一样,这个题要求的合唱队形要求两边低,中间高,也就是前一段是递增的,后一段是递减的,注意:并不一定正好分为左右人数相等的两半。
从左边开始,求出到每个数存在的最长上升子序列,然后再从右边做一次一样的操作,这样就能求出每个数字所在的上升子序列与下降子序列,分别用两个数组b和c记录
然后for循环进行枚举,求出b[i]+c[i]的最大值,最大值所对应的i就是i作为最高点时,场上留下的人最多,最后结果就是n-maxn+1,因为i位置的同学在计算maxn的时候被算了两次。
代码
#include
#define N 10100
#define INF 0x7f
using namespace std;
int a[N],b[N],c[N];
int main() {
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%d",&a[i]);
}
for(int i=1; i<=n; i++) {
b[i]=1;
for(int j=1; j
if(a[i]>a[j]&&b[i]
b[i]=b[j]+1;
}
}
}
for(int i=n; i>0; i--) {
c[i]=1;
for(int j=n; j>i; j--) {
if(a[i]>a[j]&&c[i]
c[i]=c[j]+1;
}
}
}
int maxn=-INF;
for(int i=1; i<=n; i++) {
if (b[i]+c[i]>maxn)
maxn=b[i]+c[i];
}
maxn=n-maxn+1;
cout<
return 0;
}