动态规划之合唱队形问题

代码:

麻烦的思路(java):

import java.util.Scanner;

//N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,而不改变其他同学的位置,使得剩下的K位同学排成合唱队形。
//合唱队形要求:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,则他们的身高满足T1<T2...<Ti>Ti+1>…>TK(1<=i<=K)。
//已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成最长的合唱队形。

public class tutti {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();
		int height[] = new int[N];
		int maxNumber[] = new int[N];
		int max = -1;
		
		for (int i = 0; i < N; i++) {
			height[i] = sc.nextInt();
		}
		
		for (int i = 0; i < N; i++) {
			int m = -1;
			left(i,height,maxNumber);
			for (int j = 0; j <= i; j++) {
				if(maxNumber[j]>m){
					m = maxNumber[j];
				}
			}
			int n = -1;
			right(i,height,maxNumber);
			for (int j = i; j < N; j++) {
				if(maxNumber[j]>n){
					n = maxNumber[j];
				}
			}
			if((m+n-1)>max){
				max = m+n-1;
			}
		}
		System.out.println(max);
	}

	private static void right(int i, int[] height, int[] maxNumber) {
		for (int j = i; j < height.length; j++) {
			maxNumber[j] = 1;
			for (int j2 = i; j2 < j; j2++) {
				if((height[j]<=height[j2])&&(maxNumber[j2]+1>maxNumber[j])) maxNumber[j] = maxNumber[j2]+1;
			}
		}
	}

	private static void left(int i, int[] height, int[] maxNumber) {
		for (int j = 0; j <= i; j++) {
			maxNumber[j] = 1;
			for (int j2 = 0; j2 < j; j2++) {
				if((height[j]>=height[j2])&&(maxNumber[j2]+1>maxNumber[j])) maxNumber[j] = maxNumber[j2]+1;
			}
		}
	}
}

  简单的思路(java):

public class test {  
    public static void main(String[] args) {  
        int []high={176,163,150,140,180,130,167,160};  
        int []up=new int[8];   //记录每位同学的最大上升子序列  
        int []down=new int[8]; //记录每位同学的最大下降子序列  
        for(int i=0;i<high.length;i++){  
            up[i]=1; //每位同学的最大上升子序列初始值为1  
            for(int j=0;j<i;j++){  
                if((high[j]<high[i])&&(up[i]<up[j]+1)) up[i]=up[j]+1; //前i位同学的最大上升子序列的最大值再加1  
            }  
        }  
        for(int i=high.length-1;i>=0;i--){  
            down[i]=1;  
            for(int j=high.length-1;j>i;j--){  
                if((high[j]<high[i])&&(down[i]<down[j]+1)) down[i]=down[j]+1; //后N-i位同学的最大下降子序列的最大值再加1  
            }  
        }  
        int max=0; //设每位同学所形成的最长合唱队形的最大值初值为0  
        int index=0; //设最大值对应的索引为0  
        for(int i=0;i<high.length;i++){  
            if(up[i]+down[i]-1>max) {  
                max=up[i]+down[i]-1; //求得每位同学所形成的最长合唱队形的最大值  
                index=i;  //求得对应的索引  
            }  
        }  
        System.out.println("最长合唱队形的长度为:"+max);  
        System.out.println("对应的是第"+(index+1)+"位同学,需要"+(high.length-max)+"位同学出列");  
  
    }  
}  

  

原文地址:https://www.cnblogs.com/-rainbow-/p/7999305.html