合唱队列问题

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

合唱队列说明:

N位同学中,使(N-K)位出列,使得剩下的满足条件:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,   则他们的身高满足存在i(1<=i<=K)使得T1<T2<......<Ti-1<Ti>Ti+1>......>TK。

计算出最少需要出列的同学数。

 

#include "iostream"
#include "vector"
#include "algorithm"

using namespace std;

//需要关注每个同学左边满足合唱队列的数(加上自己)
//总人数 - 该数所在队列人数 + 1 = 需要出队的人数
/*
186   186     150   200     163    130    197   200   orig_num

1      1      1      2       2      1      3     4       递增计数

200     197    130    163    200    150    186   186              反向orig_num

1      1      1       2     3      2      3       3      递减计数

然后将每个数的递增计数和递减计数相加

186   186    150    200    163    130    197    200   orig_num

1      1      1      2       2     1      3      4       递增计数

3      3      2      3       2     1      1      1       递减计数

4      4      3      5       4     2      4      5       相加,计算队列长度(自己在递增和递减中被重复计算)


如163这个数

在递增队列中有2个人数
150  163

在递减队列中有2个人数
163  130

那么163所在队列中就有3个人

150  163  130

*/
void calculate_num(vector<int> orig_num, vector<int> &num)
{
    for(int i = 1; i < orig_num.size(); ++i)
    {
        for(int j = i - 1; j >= 0; --j)
        {
            if((orig_num[i] > orig_num[j]) && (num[i] < num[j] + 1))
            {
                num[i] = num[j] + 1;
            }
        }
    }
}


int main()
{
    int n = 0;
    int tmp = 0;


    while(cin >> n)
    {

        vector<int> num1(n,1);//递增
        vector<int> num2(n,1);//递减
        //必须放到while中(局部变量),不然多次输入会使orig_num.size()大与n
        //从而导致num1和num2越界
        vector<int> orig_num;

        for(int i = 0; i< n; ++i)
        {
            cin >> tmp;
            orig_num.push_back(tmp);
        }

        calculate_num(orig_num, num1);
        reverse(orig_num.begin(), orig_num.end());
        calculate_num(orig_num, num2);
        reverse(num2.begin(), num2.end());

        int max_num = 0;

        for(int i = 0; i < n; ++i)
        {
            if(num1[i] + num2[i] > max_num)
            {
                max_num = num1[i] + num2[i];
            }
        }

        cout<<n - max_num + 1<<endl;

    }

    return 0;
}

 

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值