zoukankan      html  css  js  c++  java
  • 合唱队

    题目描述

    计算最少出列多少位同学,使得剩下的同学排成合唱队形

    说明:

    N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
    合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,   则他们的身高满足存在i(1<=i<=K)使得T1<T2<......<Ti-1<Ti>Ti+1>......>TK。
    你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

    请注意处理多组输入输出!

    输入描述:

    整数N

    输出描述:

    最少需要几位同学出列

    示例1

    输入

    8
    186 186 150 200 160 130 197 200
    

    输出

    4

    #include <bits/stdc++.h>
    using namespace std;
    //这题采用的是动态规划的思想,但是我已开始没有思路,后来看了评论区的思路后,才重新写的
    //然后,无意中容易犯一个错误:题目问的是需要去掉几个人,而动态规划求出的两个标记数组则是表示合唱团剩余的人数!!!
    //从左向右或从右向左标记的代码值得铭记!!!别试图用O(n)的方式求解,至少目前没想到也没看到~
     int main(){
        int i, j, t, n;
        vector<int> vi, fgL, fgR;
        while(scanf("%d", &n) != EOF){
            vi.clear();
            fgL = vector<int>(n, 1); //初始状态
            fgR = vector<int>(n, 1);
            for(i=0; i<n; i++){
                scanf("%d", &t);
                vi.push_back(t);
            }
         //状态转移
    for(i=1; i<n; i++){ //从左向右遍历 for(j=i-1; j>=0; j--){ if(vi[i]>vi[j] && fgL[j]>=fgL[i]) fgL[i] = fgL[j] + 1; } } for(i=n-2; i>=0; i--){ //从右向左遍历 for(j=i+1; j<n; j++){ if(vi[i]>vi[j] && fgR[j]>=fgR[i]) fgR[i] = fgR[j] + 1; } } t = 0; for(i=0; i<n; i++) if(fgL[i]+fgR[i] > t) t = fgL[i] + fgR[i]; printf("%d ", n+1-t); //这里实际为n-(t-1) t-1的原因是第 i 个位置重复统计了! } return 0; }

    总结:动态规划的想法,感觉不是很复杂,但是为什么每次都没有思路???也许练得还不够多吧!这个题挺经典的,之前碰见过类似的题目,基本特征是:从左向右遍历标记,再从右向左遍历标记,最后就得到了以每个位置出发的情况了!现在仔细想想,是不是每次标记前都是初始化为1呢?有点忘了,这个问题暂时存疑。

    其次,因为是两轮标记,所以以每个位置出发的情况被重复统计了一次,所以要明白这点!

  • 相关阅读:
    [NC13331]城市网络
    Codeforces Round #638 (Div. 2)
    牛客练习赛62
    “科大讯飞杯”第18届上海大学程序设计联赛春季赛暨高校网络友谊赛
    Codeforces Round #635 (Div. 2)
    Codeforces Round #631 (Div. 2)
    牛客每日一题
    Codeforces Round #627 (Div. 3)
    MySQL查看建表语句
    Oracle的number数据类型
  • 原文地址:https://www.cnblogs.com/heyour/p/12525609.html
Copyright © 2011-2022 走看看