华为机试-合唱队(较难)

合唱队

http://www.nowcoder.com/practice/6d9d69e3898f45169a441632b325c7b4

题目描述

计算最少出列多少位同学,使得剩下的同学排成合唱队形

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

注意不允许改变队列元素的先后顺序
请注意处理多组输入输出!

输入

8
186 186 150 200 160 130 197 200

输出

4

需要出列的同学最少 = 保留下来的同学最多。
最后排成的合唱队是△先递增再递减的,中间会有一个最高的中心同学i。
当中心同学i左边的同学+右边同学最多的时候,保留下的同学最多。
即i左边的最长递增子序列 + i右边的最长递减子序列最大的时候是最优解。
先求i处最长递增子序列的个数:dp_up[i]=max(dp_up[i],dp_up[j]+1); 其中j<i;从左往右循环。
再求i处最长递减子序列的个数:dp_down[i]=max(dp_down[i],dp_down[j]+1);其中j>i;从右往左循环。
当i处dp_up[i]+dp_down[i]最大时,i就是中心同学,此时队列中人数dp_up[i]+dp_down[i]-1
出列的人数:总人数num-(dp_up[i]+dp_down[i]-1)

#include<iostream>
#include<vector>
using namespace std;
int main(){
    int num;
    while(cin>>num){
        vector<int> temp;
        vector<int> dp_up(num,1);
        vector<int> dp_down(num,1);
        for(int i=0;i<num;i++){
            int a;
            cin>>a;
            temp.push_back(a);
        }
        //dp_up[i]最长上升子序列个数
        for(int i=1;i<temp.size();i++){
            for(int j=i-1;j>=0;j--){
                if(temp[j]<temp[i]){
                    dp_up[i]=max(dp_up[i],dp_up[j]+1);
                }
            }
        }
        //dp_down[i]最长下降子序列个数
        for(int i=temp.size()-2;i>=0;i--){
            for(int j=i+1;j<temp.size();j++){
                if(temp[j]<temp[i]){
                    dp_down[i]=max(dp_down[i],dp_down[j]+1);
                }
            }
        }
        int maxvalue=0;
        for(int i=0;i<temp.size();i++){
            if(dp_up[i]+dp_down[i]>maxvalue)
                maxvalue=dp_up[i]+dp_down[i];
        }
        cout<<num-(maxvalue-1)<<endl;

    }
}
全部评论

相关推荐

头像
11-26 15:46
已编辑
中南大学 后端
字节国际 电商后端 24k-35k
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
6
9
分享
牛客网
牛客企业服务