洛谷 P1091 合唱队形

洛谷 P1091 合唱队形

$$传送门在这里呀$$


题目描述

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

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

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


输入输出格式

输入格式:

共二行。

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

第二行有\(n\)个整数,用空格分隔,第\(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 20\);

对于全部的数据,保证有\(n \le 100\)。


思路

此题是动态规划的基础题之一,我太lj了,最后想不出来怎么处理来得到最大值qwq

和日常生活中照照片一样,(为了美观),这个题要求的合唱队形要求两边低,中间高,也就是前一段是递增的,后一段是递减的,注意:

并不一定正好分为左右人数相等的两半.

从左边开始,求出到每个数存在的最长上升子序列,然后再从右边做一次一样的操作,这样就能求出每个数字所在的上升子序列与下降子序列,分别用两个数组b和c记录

然后for循环进行枚举,求出b[i]+c[i]的最大值,最大值所对应的i就是i作为最高点时,合唱队里留下的人最多,最后结果就是n-maxn+1,因为i位置的同学在计算maxn的时候算了两边,所以加1。


代码

#include<bits/stdc++.h>
#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<i; j++) {
if(a[i]>a[j]&&b[i]<b[j]+1) {
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[j]+1) {
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<<maxn<<'\n';
return 0;
}
上一篇:552. Student Attendance Record II


下一篇:jenkins vue前端项目打包