洛谷 P1091 合唱队形

      洛谷 P1091 合唱队形

题目描述

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

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

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

输入输出格式

输入格式:

共二行。

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

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

输出格式:

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

输入输出样例

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

说明

对于50%的数据,保证有 n20 ;

对于全部的数据,保证有 n100 。

思路:经典的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 - ans);  //第一遍输错了,输出ans,只有20分
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/v-vip/p/9338071.html