1. 程式人生 > >洛谷-【動態規劃】- P1091 合唱隊形

洛谷-【動態規劃】- P1091 合唱隊形

題目描述

NN位同學站成一排,音樂老師要請其中的(N-KN−K)位同學出列,使得剩下的KK位同學排成合唱隊形。

合唱隊形是指這樣的一種隊形:設K位同學從左到右依次編號為1,2,…,K1,2,…,K,他們的身高分別為T_1,T_2,…,T_KT1​,T2​,…,TK​, 則他們的身高滿足T_1<...<T_i>T_{i+1}>…>T_K(1 \le i \le K)T1​<...<Ti​>Ti+1​>…>TK​(1≤i≤K)。

你的任務是,已知所有N位同學的身高,計算最少需要幾位同學出列,可以使得剩下的同學排成合唱隊形。

輸入輸出格式

輸入格式:

共二行。

第一行是一個整數N(2 \le N \le 100)N(2≤N≤100),表示同學的總數。

第二行有nn個整數,用空格分隔,第ii個整數T_i(130 \le T_i \le 230)Ti​(130≤Ti​≤230)是第ii位同學的身高(釐米)。

輸出格式:

一個整數,最少需要幾位同學出列。

輸入輸出樣例

輸入樣例#1: 複製

8
186 186 150 200 160 130 197 220

輸出樣例#1: 複製

4

說明

對於50%的資料,保證有n \le 20n≤20;

對於全部的資料,保證有n \le 100n≤100。

題目:基於最長上升子序列的改編,找到最長的上升的子序列,然後用總長度減去這長度就是最後的結果,但本題是從兩端開始的要求最長上升的,所以那就分別從兩端的開始遍歷一遍找出最長的上升子序列,然後在相同位置取最長的那個序列就行了,最後用總長度減去這個就是結果。

import java.util.*;
/*
 *合唱隊形
 */
public class Main{
	public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        int[] a=new int[n+2];
        for(int i=1;i<=n;i++) {
        	a[i]=in.nextInt();
        }
        int[][] dp=new int[2][n+1];
        for(int i=1;i<=n;i++) {
        	dp[0][i]=1;
        	for(int j=1;j<i;j++) {
        		if(a[i]>a[j]) {
        			dp[0][i]=Math.max(dp[0][i], dp[0][j]+1);
        		}
        	}
        }
        for(int i=1;i<=n;i++) {
        	dp[1][i]=1;
        	for(int j=1;j<i;j++) {
        		if(a[i]<a[j]) {
        			dp[1][i]=Math.max(dp[1][i], Math.max(dp[0][j], dp[1][j])+1);
        		}
        	}
        }
        int max=0;
        for(int i=1;i<=n;i++) {
        	max=Math.max(max, Math.max(dp[1][i], dp[0][i]));
        }
        System.out.println(n-max);
    }
}