zoukankan      html  css  js  c++  java
  • vijos 1098 合唱队形

    描述

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

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

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

    格式

    输入格式

    输入的第一行是一个整数N(2<=N<=100),表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti(130<=Ti<=230)是第i位同学的身高(厘米)。

    输出格式

    输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。

    样例1

    样例输入1

    8
    186 186 150 200 160 130 197 220

    样例输出1

    4

    限制

    每个测试点1s

    来源

    NOIP 2004

    (转自https://vijos.org/p/1098)


      一看还真不好处理,至于高度从小到大再从大到小就先分开来看,先把从左边开始的不下降子序列求出来,不如用个l数组

    l[i]表示从到i这个点最长的不下降子序列的长度,再用个r数组,表示从右边到i这个点最长不下降子序列的长度(注意是从右到左),然后再拼起来(l[i] + r[i]),减去一个人(第i个人算重了)就是i这个人当做k时最大可以选用的人的数量。

      这样的看得话就简单多了,求2次最长不下降子序列,再for循环跑一趟就把最大可以选用的人数算出来。注意,l,r数组的初值是1(1个

    人也可以排成这样的序列)

    Code

     1 /*
     2  * vijos.org
     3  * Problem#1098
     4  * Accepted
     5  * Time:45ms
     6  * Memory:556k
     7  */
     8 #include<iostream>
     9 #include<cstdio>
    10 #include<cctype>
    11 #include<cstring>
    12 using namespace std;
    13 template<typename T>
    14 inline void readInteger(T& u){
    15     char x;
    16     while(!isdigit((x = getchar())));
    17     for(u = x - '0';isdigit((x = getchar()));u = ((u << 3) + (u << 1) + x - '0'));
    18     ungetc(x, stdin);
    19 }
    20 int n;
    21 int *l,*r;
    22 int *h;
    23 void init(){
    24     readInteger(n);
    25     h = new int[(const int)(n + 1)];
    26     l = new int[(const int)(n + 1)];
    27     r = new int[(const int)(n + 1)];
    28     for(int i = 1;i <= n;i++){
    29         readInteger(h[i]);
    30     }
    31 }
    32 int result;
    33 void solve(){
    34     for(int i = 1;i <= n; i++){
    35         l[i] = r[n - i + 1] = 1; 
    36         for(int j = 1;j < i; j++){
    37             if(h[i] > h[j] && l[i] <= l[j])
    38                 l[i] = l[j] + 1;
    39             if(h[n - i + 1] > h[n - j + 1] && r[n - i + 1] <= r[n - j + 1])
    40                 r[n - i + 1] = r[n - j + 1] + 1;
    41         }        
    42     }
    43     for(int i = 1;i <= n;i++)
    44         if(l[i] + r[i] > result)    result = l[i] + r[i];
    45 }
    46 int main(){
    47     init();
    48     solve();
    49     printf("%d",n - result + 1);
    50     return 0;
    51 }
  • 相关阅读:
    1 TKinter小窗口及标题
    css之padding,marging
    css之opacity
    css之position
    Leetcode 1368 使网格图至少有一条有效路径的最小代价
    Leetcode 137 只出现一次的数字II
    Leetcode 135分发糖果
    Leetcode 134加油站
    Leetcode 124 二叉树的最大路径和
    Leetcode 5346 二叉树中的列表
  • 原文地址:https://www.cnblogs.com/yyf0309/p/5716172.html
Copyright © 2011-2022 走看看