题目描述
功能:
计算最少出列多少位同学,使得剩下的同学排成合唱队形
说明:
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足存在i(1<=i<=K)使得T1<T2<......<Ti-1<Ti>Ti+1>......>TK。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入描述:
整数N
输出描述:
最少需要几位同学出列
示例:
输入: 8
186 186 150 200 160 130 197 200
输出: 4
思路:
对给定数组进行两次最长递增子序列,一次正序,一次逆序; 将两遍动态规划的结果相加取最大值,需要出列的同学就是:
总人数 - 动态规划结果最大值 + 1;例如:
正序 :186 186 150 200 160 130 197 200 逆序 :200 197 130 160 200 150 186 186
结果 :1 1 1 2 2 1 3 4 结果 :1 1 1 2 3 2 3 3
以160为例子,相加代表的意思可以理解成
正序 150 160
逆序 160 130
这样160所在的队列即为 150 160 130, 需要出队的人数即为: 总人数 - 相加最大和 + 1;
代码:
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int num = sc.nextInt();
int[] arr = new int[num];
int[] dp = new int[num];
int[] revdp = new int[num];
for(int i = 0; i < num; i++)
arr[i] = sc.nextInt();
for(int i = 0; i < num; i++){
dp[i] = 1;
for(int j = 0; j < i; j++ )
if(arr[i] > arr[j]) dp[i] = Math.max(dp[i], dp[j] + 1);
}
for(int i = num - 1; i >= 0; i--){
revdp[i] = 1;
for(int j = num - 1; j > i; j--)
if(arr[i] > arr[j]) revdp[i] = Math.max(revdp[i], revdp[j] + 1);
}
int max = 0;
for(int i = 0; i < num; i++)
max = Math.max(max, dp[i] + revdp[i]);
System.out.println(num - max + 1);
}
}
}