zoukankan      html  css  js  c++  java
  • 洛谷 P1091 合唱队形 最长上升、下降子序列

    P1091 合唱队形

    • 时空限制1s / 128MB

    题目描述

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

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

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

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

    说明

    对于50%的数据,保证有n<=20;

    对于全部的数据,保证有n<=100。

    -----------------------------------------------------------------------------------------------------------------

    最长上升子序列+最长下降子序列

    写这道题之前,你要知道如何求一个序列的最长上升/下降子序列

    可以看我的一篇随笔:http://www.cnblogs.com/lpl-bys/p/7701945.html

    dpu[i][j]表示从第i个数到第j个数构成的序列里的最长上升子序列

       dpd[i][j]表示从第i个数到第j个数构成的序列里的最长下降子序列

    需要注意的是dpu[i][j]和dpd[i][j]所表示的最长子序列都必须从第i个数开始的,这就不便于后面把这两个序列合起来

    所以我们需要再开另外两个二维数组:

    up[i][j]表示从第i个数到第j个数构成的序列里的最长上升子序列

    dow[i][j]表示从第i个数到第j个数构成的序列里的最长下降子序列

    可以看到,这两个数组才是真正的表示从第i个数到第j个数构成的序列里的最长上升/下降子序列的长度(即不必从第i个数开始)

    后面就容易多了

    具体看代码体会吧:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 #define maxn 233
     5 using namespace std;
     6 int read();
     7 int n,a[maxn],dpu[maxn][maxn],dpd[maxn][maxn],ans,up[maxn][maxn],dow[maxn][maxn];
     8 int main(){
     9     n=read();
    10     for(int i=1;i<=n;i++) a[i]=read();
    11     for(int i=1;i<=n;i++)
    12        for(int j=i;j>0;j--){
    13            for(int k=j;k<=i;k++){
    14               if(j==k) dpu[k][i]=dpd[k][i]=1;//不同于不严格的,因为是求严格上升/下降序列的,所以需要这一步初始化
    15               if(a[j]<a[k]&&dpu[k][i]+1>dpu[j][i]) dpu[j][i]=dpu[k][i]+1;
    16               if(a[j]>a[k]&&dpd[k][i]+1>dpd[j][i]) dpd[j][i]=dpd[k][i]+1;
    17               up[j][i]=max(up[j][i],dpu[k][i]);
    18               dow[j][i]=max(dow[j][i],dpd[k][i]);
    19         }
    20         up[j][i]=max(up[j][i],dpu[j][i]);
    21         dow[j][i]=max(dow[j][i],dpd[j][i]);
    22        }
    23     ans=0;
    24     for(int i=0;i<=n;i++)
    25     if(up[1][i]+dow[i+1][n]>ans) ans=up[1][i]+dow[i+1][n];
    26     printf("%d",n-ans);
    27     return 0;
    28 }
    29 int read(){
    30     int ans=0,f=1;char c=getchar();
    31     while('0'>c||c>'9'){if(c=='-')f=-1;c=getchar();}
    32     while('0'<=c&&c<='9')ans=ans*10+c-48,c=getchar();return ans*f;
    33 }
    最长上升/下降子序列
  • 相关阅读:
    AIR配置文件(*app.xml)说明
    重学AS3之基础知识重点记忆
    重学AS3之高级知识重点记忆
    FLEX AIR添加系统托盘图标步骤
    FLASH组件在FLEX中使用
    ASP.NET入门教程:数据绑定
    ASP.NET入门教程:Web表单维持对象的ViewState
    ASP.NET入门教程:简单的ASP.NET页面
    ASP.NET入门教程:事件句柄
    ASP.NET入门教程:TextBox控件
  • 原文地址:https://www.cnblogs.com/lpl-bys/p/7738714.html
Copyright © 2011-2022 走看看