Chorus Formation - Dynamic Programming

Link: https://www.nowcoder.com/questionTerminal/cf209ca9ac994015b8caf5bf2cae5c98?answerType=1&f=discussionSource
: Niuke.com

N students stand in a row, and the music teacher asks (NK) students to stand out, so that the remaining K students can form a chorus formation without switching positions. The chorus formation refers to such a formation: Suppose the K students are numbered 1, 2, ..., K from left to right, and their heights are T1, T2, ..., TK respectively, then their heights satisfy T1 < T2 < ... < Ti , Ti > Ti+1 > ... > TK (1 <= i <= K). Your task is to know the heights of all N students, and calculate the minimum number of students who need to be listed, so that the remaining students can form a chorus formation.

Enter a description:

The first line of input is an integer N (2 <= N <= 100), indicating the total number of classmates.
The first line has n integers separated by spaces. The i-th integer Ti (130 <= Ti <= 230) is the height (cm) of the i-th student.

Output description:

May include multiple sets of test data, for each set of data,
The output includes one line, which contains only one integer, which is the minimum number of students who need to come out.

Example 1

enter

8
186 186 150 200 160 130 197 220

output

4

NOTE: Dynamic programming, longest non-decreasing subsequence (LIS) deformation. The title requires finding subsequences that decrease from the middle to both sides.

dp[i]: The longest increasing subsequence ending with i. Dynamic equation: dp[i] = max{dp[i],dp[j]+1}. Initialize the boundary dp[i]=1.

1. Traversing from left to right, find the longest increasing subsequence dp1[i] in the left half of the middle

2. Traversing from right to left, find the longest increasing subsequence dp2[i] in the middle right half

3. Add the longest increasing subsequences of the left and right parts of the middle (i). At this time, the largest number in the middle is repeated twice, and the longest subsequence length res that decreases from the middle to both sides subtracts a repeated number in the middle.

4. The last students listed are the remaining numbers that do not form the longest subsequence, just take n-(res-1).

code:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n+1];
        for(int i = 0; i<n; i++)a[i] = sc.nextInt();
        int[] dp1 = new int[n+1];//从前往后以i为结尾的最长递增子序列
        int[] dp2 = new int[n+1];//从后往前以i为结尾的最长递增子序列
        for(int i = 0; i<n; i++){
            dp1[i] = 1;
            for(int j = 0; j<i; j++){
                if(a[i]>a[j] && dp1[j]+1 > dp1[i]){
                    dp1[i] = dp1[j]+1;
                }
            }
           // System.out.print(dp1[i]+" ");
        }
//        System.out.println();
//        for(int i = 0; i<n; i++){//这样是错误的,必须从中间向两边寻找,中间高向两边减低,
//        这样还是与之前一样的顺序寻找,会把开头的算上,而不是从中间向两边寻找。可以输出看看。
//            dp2[i] = 1;
//            for(int j = 0; j<i; j++){
//                if(a[i]<a[j] && dp2[j]+1 > dp2[i]){
//                    dp2[i] = dp2[j]+1;
//                }
//            }
//            System.out.print(dp2[i]+" ");
//        }
        for(int i = n-1; i>=0; i--){
            dp2[i] = 1;
            for(int j = n-1; j>=i; j--){//从后向前寻找最长递增子序列
                if(a[i]>a[j] && dp2[j]+1 > dp2[i]){
                    dp2[i] = dp2[j]+1;
                }
            }
            //System.out.print(dp2[i]+" ");
        }
        //System.out.println();
        int res = 0;
        for(int i = 0; i<n; i++){
            res = Math.max(res,dp1[i]+dp2[i]);
        }//因为以i为结尾的子序列,自身重复了两次,所以最后还要减去自身重复的1
        System.out.println(n-res+1);//n-(res-1)
    }
}

 

 

 

 

Guess you like

Origin blog.csdn.net/qq_44985985/article/details/108132314