合唱队站队

来源:互联网 发布:zemax反射镜怎么优化 编辑:程序博客网 时间:2024/04/28 00:11

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

说明:

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


输入描述:

整数N

输出描述:

最少需要几位同学出列

输入例子:
8186 186 150 200 160 130 197 200
输出例子:
4

解题思路:


首先计算每个数在最大递增子串中的位置

186 186 150 200 160 130 197 200 quene

1 1 12 2 1 3 4递增计数


然后计算每个数在反向最大递减子串中的位置--->计算反向后每个数在最大递增子串中的位置

200197 130160 200150 186186 反向quene

1 1 12 3 2 3 3递减计数


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

186 186 150 200 160 130 197 200 quene

1 1 12 2 1 3 4递增计数

3 3 23 2 1 1 1递减计数

4 4 35 4 2 4 5每个数在所在队列的人数+1(自己在递增和递减中被重复计算)


如160这个数

在递增队列中有2个人数

150 160

在递减队列中有2个人数

160 130

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

150 160 130


每个数的所在队列人数表达就是这个意思


总人数 - 该数所在队列人数 = 需要出队的人数


#include <iostream>#include <vector>#include <algorithm>using namespace std;void calIncSub(vector<int> quene, vector<int> &Num){for(int i=1;i<quene.size();i++)for(int j=i-1;j>=0;j--)if(quene[j]<quene[i] && Num[i]<Num[j]+1)//找到前面比当前小的,且【能获得的最大子串计数】Num[i]=Num[j]+1;}int main(){int n;int h;        while(cin>>n){        vector<int> quene;        vector<int> incNum(n,1);//初始化为n个1        vector<int> decNum(n,1);        vector<int> totalNum;        for(int i=0;i<n;i++){            cin >> h;            quene.push_back(h);            }        calIncSub(quene,incNum);//找递增子串计数        reverse(quene.begin(),quene.end());//翻转,即找反向的子串计数        calIncSub(quene,decNum);        reverse(decNum.begin(),decNum.end());//反向递增即正向递减        int max=0;        for(int i=0;i<n;i++){            totalNum.push_back(incNum[i]+decNum[i]);            if(totalNum[i]>max)                max=totalNum[i];        }        cout << n-max+1 <<endl;    }return 0;}

注意问题:

(1)vector只能初始化为n个几,不能每个值不同的初始化

(2)使用reverse函数必须包含头文件<algorithm>

(3)vector未初始化或赋值之前不能使用下标,即vec[i]表示


1 0
原创粉丝点击