华为机试HJ24:合唱队
Posted 翟天保Steven
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了华为机试HJ24:合唱队相关的知识,希望对你有一定的参考价值。
题目描述:
计算最少出列多少位同学,使得剩下的同学排成合唱队形
说明:
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足存在i(1<=i<=K)使得T1<T2<......<Ti-1<Ti>Ti+1>......>TK。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
注意:不允许改变队列元素的先后顺序 且 不要求最高同学左右人数必须相等
请注意处理多组输入输出!
备注:
1<=N<=3000
输入描述:
有多组用例,每组都包含两行数据,第一行是同学的总数N,第二行是N位同学的身高,以空格隔开
输出描述:
最少需要几位同学出列
示例:
输入:
8
186 186 150 200 160 130 197 200
输出:
4
解题思路:
这是一个最长子序列问题,也是动态规划问题。在不影响原先排列的前提下,抽出最少多少个人可以组成合唱序列;首先从左往右,计算从低到高截止到每个人所能组成的最大子序列;再从右向左,计算从低到高截止到每个人所能组成的最大子序列;这两个子序列的数值相加再减一,因为本人加了两次,这样得到的就是所能组成合唱序列的最大人数,那么抽出的最少人数就是总人数减序合唱序列最大人数。
测试代码:
#include <iostream>
using namespace std;
int main()
{
int number=0;
int people[3000],left[3000],right[3000];
while(cin>>number)
{
for(int i=0;i<number;++i)
{
cin>>people[i];
left[i]=1;
for(int j=0;j<i;++j)
{
if(people[i]>people[j])
{
left[i]=max(left[i],left[j]+1);
}
}
}
for(int i=number-1;i>=0;--i)
{
right[i]=1;
for(int j=number-1;j>i;--j)
{
if(people[i]>people[j])
{
right[i]=max(right[i],right[j]+1);
}
}
}
int sum=0;
for(int i=0;i<number;++i)
{
if(left[i]+right[i]-1>sum)
{
sum=left[i]+right[i]-1;
}
}
cout<<number-sum<<endl;
}
return 0;
}
以上是关于华为机试HJ24:合唱队的主要内容,如果未能解决你的问题,请参考以下文章