合唱队形java_动态规划之合唱队形问题
发布日期:2021-06-24 17:42:02 浏览次数:3 分类:技术文章

本文共 1614 字,大约阅读时间需要 5 分钟。

问题描述:

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

问题分析:

假设第i位同学为个子最高的同学,我们先对其左边的同学求最大上升子序列,再对其右边的同学求最大下降子序列,然后两者相加再减1(第i位同学被重复计算 了一次),便得到第i位同学为最高个时所能排成的最长合唱队形。如果我们对这N位同学都执行此操作,便可得到每位同学为最高个时所能排成的最长合唱队形, 选取其中最长的合唱队形作为最终的结果。

从 上述的分析可以看出,我们可以将问题分成互相不独立的子问题,只要得到子问题的最优解,便可得到整个问题的最优解。我们可以用一张表来记录所有已解决问题 的答案,从而避免了重复计算。这里的一个关键问题便是:如何得到第i位同学的最大上升子序列和最大下降子序列。假如这N位同学的身高分别 为:176,163,150,180,170,130,167,160,我们用up[i]来记录第i位同学的最大上升子序列。如果要得到180同学为最高 个时的最大上升子序列即up[4],我们只需求出前3位同学所能形成的最大上升子序列,将其加1即可;要得到前3位同学所形成的最大上升子序列,便要求得 前2位同学的最大上升子序列,再加上1即可;同样要得到前2位同学的最大上升子序列,便要求得第1位同学的最大上升子序列。因此这是一个递推关系,只要我 们将前i个同学为最高个时做形成的最大上升子序列的值记录下来,取其中最大值加1便可得到第i位同学的最大上升子序列即up[i]。同理我们用 down[i]来记录第i位同学的最大下降子序列,只要我们将后(N-i)位同学每位同学为最高个时的最大下降子序列记录下来,取其中最大者再加1便可得 到第i位同学为最高个时的最大下降子序列即down[i]。那么,第i位同学为最高个时做能形成的最长合唱队形的长度为up[i]+down[i]-1。 求得所有同学为最高个时所能形成的最长合唱队形的长度,取其中最大值为最终的结果。

public class Main {

public static void main(String[] args) {

int []high={176,163,150,180,170,130,167,160};

int []up=new int[8];   //记录每位同学的最大上升子序列

int []down=new int[8]; //记录每位同学的最大下降子序列

for(int i=0;i

up[i]=1; //每位同学的最大上升子序列初始值为1

for(int j=0;j

if((high[j]

}

}

for(int i=high.length-1;i>=0;i--){

down[i]=1;

for(int j=high.length-1;j>i;j--){

if((high[j]

}

}

int max=0; //设每位同学所形成的最长合唱队形的最大值初值为0

int index=0; //设最大值对应的索引为0

for(int i=0;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://blog.csdn.net/weixin_34190683/article/details/114932636 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:java变量怎么进行百分比_在Java中显示百分比
下一篇:用流密码实现加密java语言_使用java的流密码

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月10日 08时51分55秒