题目
题目描述
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学不交换位置就能排成合唱队形。
合唱队形定义:设K位同学从左到右依次编号为1, 2, …, K,他们的身高分别为T1, T2, …, TK,
则他们的身高满足T1 < T2 < … < Ti, Ti > Ti+1 > … > TK (1 <= i <= K)。
要求:已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入
输入的第一行是一个整数N,表示同学的总数。第一行有n个整数,用空格分隔,第i个整数Ti是第i位同学的身高(厘米)。
输出
输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。
解题思路
首先将n个同学的身高存入a[n]中 ,当然数组大小需要大于该值
【解】假设队中最高的那个人的序列为 i ,那么他左边递增序列与右边递减序的和 列是所有人中最长的
所以我们第一步需要找到每个同学左边递增序列的个数
例如有8位同学,身高分别为 186 186 150 200 160 130 197 200
递增序列 inc[n] 的求法,每一个数只需要看每个数的序列值,设0<j<i<n , 若 a[j] < a[i] ,那么inc[i] = inc[j] + 1; 后面的数永远会添加之前出现的递增子串后,
而且这里注意,我们最后得到inc[i] 应该是之前所有的inc[j]中最大那个+1
186 | 186 | 150 | 200 | 160 | 130 | 197 | 200 |
1 | 1 | 1 | 2 | 2 | 1 | 3 | 4 |
递减序列 dec[n] 的求法和上面大同小异,如法炮制,只不过是从右往左找递增
186 | 186 | 150 | 200 | 160 | 130 | 197 | 200 |
3 | 3 | 2 | 3 | 2 | 1 | 1 | 1 |
递增和递减序列都将自身算在内了,所以我们算总合唱团长度时需要减去自身的重复
代码示意
#include <iostream> #include <string> using namespace std; int main() { int N; int array[5000]; while(cin>>N) { int i,j; int inc[5000],dec[5000];//递增和递减序列 for(i = 0;i<N;i++) { cin>>array[i]; inc[i] = 1; dec[i] = 1; } if(N<=1) { cout<<0<<endl; continue; } for(i = 0;i<N;i++)//求递增子串序列 { for(j = 0;j<i;j++) { if(array[i]>array[j]&&inc[j]+1>inc[i]) inc[i]=inc[j]+1; } } for(i = N-1;i>=0;i--)//求递减子串序列 { for(j = N-1;j>i;j--) { if(array[i]>array[j]&&dec[j]+1>dec[i]) dec[i] = dec[j]+1; } } int max = 0; for(i = 0;i<N;i++) { if(max < (inc[i]+dec[i]-1)) max = inc[i]+ dec[i]-1;//求最大合唱序列人数 } cout<<N-max<<endl; } return 0; }