蓝桥杯刷题——合唱队形(线性DP、最长单调子序列)

题目描述:

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

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

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

输入格式

输入的第一行是一个整数 N,表示同学的总数。

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

输出格式

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

数据范围

2N100

,
130Ti230

输入样例:

8
186 186 150 200 160 130 197 220

输出样例:

4

思路:

因为这里是让我们求最少出列的同学人数,所以这里要使用左右两边的最长单调子序列来做,即算出每一个数在最中间时它的左右最长上升和下降子序列之和,最后比较哪个大即可,假设此时以第i个同学作为最中间达到的人数最多的话,那么此时也就是出列同学最少的情况,就可以算出最长上升和最长下降子序列之和sum,然后用总的同学人数减去sum即可。

 

AC代码:

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     public static void main(String[] args) {
 5         Scanner input = new Scanner(System.in);
 6         int n = input.nextInt();
 7         int[] arr = new int[n];
 8         for (int i = 0; i < n; i++) {
 9             arr[i] = input.nextInt();
10         }
11         
12         // 序列型
13         int[] left = new int[n + 1];
14         int[] right = new int[n + 1];
15         
16         left[1] = 1;
17         // 求第i个数左边的最长上升子序列
18         for (int i = 2; i <= n; i++) {
19             // 默认为1
20             left[i] = 1;
21             for (int j = 1; j < i; j++) {
22                 if (arr[j - 1] < arr[i - 1]) {
23                     // 选出更长的那个
24                     left[i] = Math.max(left[i], left[j] + 1);
25                 }
26             }
27         }
28         
29         right[n] = 1;
30         // 同上,最长下降子序列
31         for (int i = n - 1; i > 0; i--) {
32             // 默认为1
33             right[i] = 1;
34             for (int j = n; j > i; j--) {
35                 if (arr[j - 1] < arr[i - 1]) {
36                     // 选出更长的那个
37                     right[i] = Math.max(right[i], right[j] + 1);
38                 }
39             }
40         }
41         
42         int maxv = Integer.MIN_VALUE;
43         for (int i = 1; i <= n; i++) {
44             // 这里-1,是因为前面算left和right的时候都加了1
45             // 从中间出发,讨论两边各自单调子序列之和哪个最大,即每一个数都有可能在中间
46             int temp = left[i] + right[i] - 1;
47             maxv = Math.max(maxv, temp);
48         }
49         
50         System.out.println(n - maxv);
51     }
52 }

 

posted @ 2021-04-03 00:04  没有你哪有我  阅读(200)  评论(0编辑  收藏  举报