zoukankan      html  css  js  c++  java
  • 九度oj 题目1131:合唱队形

    题目描述:

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

    输入:

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

    输出:

    可能包括多组测试数据,对于每组数据,
    输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。

    样例输入:
    8
    186 186 150 200 160 130 197 220
    样例输出:
    4
    开始看题觉得好难,后来在沙发上躺着一拍脑门,这不就是求最长上升子序列吗,代码如下:
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #define MAX 102
     5 
     6 int high[MAX];
     7 int left[MAX];
     8 int right[MAX];
     9 //             186 186 150 200 160 130 197 220
    10 // left        0    0   0   1   1   0   2   3
    11 // right    2    2   1   2   1   0   0   0
    12 //             5     5     7   4     5   7   5   4
    13 int main(int argc, char const *argv[])
    14 {
    15     int n;
    16     while(scanf("%d",&n) != EOF) {
    17         for(int i = 0; i < n; i++) {
    18             scanf("%d",&high[i]);
    19             left[i] = 0;
    20             right[i] = 0;
    21         }
    22         for(int i = 0; i < n; i++) {
    23             int max = -1;
    24             bool isMin = true;
    25             for(int j = i -1; j >= 0; j--) {
    26                 if(high[j] < high[i] && max < left[j]) {
    27                     max = left[j];
    28                     isMin = false;
    29                 }
    30             }
    31             if(!isMin) {
    32                 left[i] = max + 1;
    33             }
    34             
    35         }
    36 
    37         for(int i = n-1; i >= 0; i--) {
    38             int max = -1;
    39             bool isMin = true;
    40             for(int j = i + 1; j < n; j++) {
    41                 if(high[j] < high[i] && max < right[j]) {
    42                     max = right[j];
    43                     isMin = false;
    44                 }
    45             }
    46             if(!isMin) {
    47                 right[i] = max + 1;
    48             }
    49         }
    50 
    51         int ans = n;
    52         for(int i = 0; i < n; i++) {
    53             int temp = n - (left[i] + right[i] + 1);
    54             if(ans > temp) {
    55                 ans = temp;
    56             }
    57         }
    58         printf("%d
    ", ans);
    59     }    
    60     return 0;
    61 }

     注释:以每一个人作为考虑对象,左值是到他的最长上升子序列,右值是他的最长下降子序列,两序列相加再减1(减不减和下标的定义有关)即为满足合唱队形的人数

  • 相关阅读:
    浅谈Java两种并发类型——计算密集型与IO密集型
    设置线程池的大小
    Java 四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecuto
    gitlab的简单操作
    GitHub vs GitLab:区别?
    前端小知识汇总
    花里胡哨的CSS集锦
    码云如何上传代码
    小程序自定义底部导航
    Vue实践过程中的几个问题
  • 原文地址:https://www.cnblogs.com/jasonJie/p/5712817.html
Copyright © 2011-2022 走看看