洛谷 P1091 合唱队形
题目描述
N 位同学站成一排,音乐老师要请其中的( N−K )位同学出列,使得剩下的 K 位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为 1,2,…,K ,他们的身高分别为 T_1,T_2,…,T_K, 则他们的身高满足 T1<...<Ti>Ti+1>…>TK(1≤i≤K) 。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入输出格式
输入格式:
共二行。
第一行是一个整数 N (2 ≤ N ≤ 100) ,表示同学的总数。
第二行有 n 个整数,用空格分隔,第 i 个整数 Ti (130 ≤ Ti ≤ 230) 是第 i 位同学的身高(厘米)。
输出格式:
一个整数,最少需要几位同学出列。
输入输出样例
说明
对于50%的数据,保证有 n≤20 ;
对于全部的数据,保证有 n≤100 。
思路:经典的DP题,前半段是求严格上升子序列,后边则是求严格下降子序列
(不知道搜索 or 贪心能不能过呢,没有试比较懒)
伪代码来一发:
for i=1到n for j=0到i-1 如果a[i]>a[j] 那么f[i]=max(f[i],f[j]+1); //f维护动态规划。 再来一个从后往前的实现方法同上。//用f1数组维护 for i=n到1 ans=max(ans,f[i]+f1[i]-1); 输出n-ans;
#include<algorithm> #include<cstring> #include<cstdio> #define M 105 using namespace std; bool x; int n, k, ans; int f[M], a[M], d[M]; int main() { scanf("%d", &n); f[1] = 1; for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= n; i++) for(int j = 0; j < i; j++) if(a[i] > a[j]) f[i] = max(f[i], f[j]+1); for(int i = n; i >= 1; i--) for(int j = n+1; j > i; j--) if(a[i] > a[j]) d[i] = max(d[i], d[j]+1); for(int i = 1; i <= n; i++) ans = max(ans, f[i] + d[i] - 1); printf("%d\n", n - ans); //第一遍输错了,输出ans,只有20分 return 0; }