笔试题9 -- 合唱队形(最长上升子序列模型)

笔试题9 – 合唱队形(最长上升子序列模型)

题目重现

题目链接:合唱队形_牛客题霸_牛客网 (nowcoder.com)

题目描述:

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

合唱队形是指这样的一种队形:设K位同学从左到右依次编号为 1,2…,K,他们的身高分别为 T1,T2,…,TK, 则他们的身高满足 t1<t2<…< ti >ti+1>…>tk−1>tk (1≤i≤k)

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

数据范围:1≤n≤1000,身高满足 130≤ti≤230

输入描述:

第一行输入一个正整数 n 表示同学的总数。

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

输出描述:

输出仅有一个整数,即最少需要几个同学出列

解题思路

在这里插入图片描述

由上图我们得知,最长符合题意的子序列无非这三种情况,于是问题转化为从左向右和从右向左分别进行一次最长递增子序列模型的组合,符合题意的子序列长度是两者之和 - 1,注意这里 - 1 是因为 i 位置分别被向左和向右各计入一次,需要去掉重复记录。最后,打印符合题意的结果时,设求得的最长子序列长为 len ,那么需要打印 n - len。

解题代码

#include <iostream>
#include <vector>
using namespace std;

// 由 1 <= i <= k 得知,最长子序列可以是:/ 或 \ 或 /\ 
//
int main() {
    int n = 0;
    cin >> n;
    vector<int> t(n, 0);
    for (auto& e : t) {
        cin >> e;
    }

    // 利用动态规划解决
    vector<int> f(n + 1);
    vector<int> g = f;
    // 从前往后填f
    for (int i = 1; i < n + 1; i++) {
        f[i] = 1;
        for (int j = 1; j < i; j++) {
            if (t[j - 1] < t[i - 1]) {
                f[i] = max(f[i], f[j] + 1);
            }
        }
    }
    // 从后往前填g
    for (int i = n; i >= 1; i--) {
        g[i] = 1;
        for (int j = i + 1; j <= n; j++) {
            if (t[j - 1] < t[i - 1]) {
                g[i] = max(g[i], g[j] + 1);
            }
        }
    }

    int len = 0;
    for (int i = 1; i <= n; i++) {
        len = max(len, f[i] + g[i] - 1);
    }
    cout << n - len << endl;

    return 0;
}

提交结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

螺蛳粉只吃炸蛋的走风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值