合唱队
问题描述:
计算最少出列多少位同学,使得剩下的同学排成合唱队形。
说明:
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位
同学排成合唱队形。
合唱队形是指这样的一种队形:
设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,
则他们的身高满足存在i(1<=i<=K)
使得T1Ti+1>……>TK。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
输入描述:
整数N
输出描述:
最少需要几位同学出列
示例1
输入
8
186 186 150 200 160 130 197 200
输出
4
问题解析
算法原理:动态规划
涉及概念:最长递增子序列
解题思路 :在N位同学中找出一个同学i,经过去除几位同学后,使得i为一个分割点,使得i之前的同学身高都小于i,i之后的同学身高都大于i。
若使去除的同学最少,则留下的同学应最大。
解题说明:
取示例 A = {186, 186, 150, 200, 160, 130, 197, 200}
(1)首先对A中所有的元素,计算每个元素在其正向最长递增子序列中的位置:
例如A[4] = 160,其所在最长子序列为{150,160,197,200},故所在位置为2。
计算结果如下:
i
0
1
2
3
4
5
6
7
A[i]
186
186
150
200
160
130
197
200
位置
1
1
1
2
2
1
3
4
(2)对A中的所有元素,计算每个数在反向递增子序列中的位置,首先对A进行逆序排列,再计算,
计算结果如下:
i
0
1
2
3
4
5
6
7
A[i]
186
186
150
200
160
130
197
200
位置
3
3
2
3
2
1
1
1
(3)对于A中每个元素i:
计算其位于正向递增子序列中的位置,则表示位于i前面,小于A[i]且保持递增的有多少个元素;
计算其位于反射递增子序列中的位置,则表示位于i后面,大于A[i]且保持递减的有多少个元素;
将每个元素所在正向递增子序列中的位置+所在反向递减子序列中的位置相加,取最大者对应的下标i,即为所求的分界点i。
计算结果如下:
i
0
1
2
3
4
5
6
7
A[i]
186
186
150
200
160
130
197
200
正向位置
1
1
1
2
2
1
3
4
反向位置
3
3
2
3
2
1
1
1
正向累加
4
4
3
5
4
2
4
5
取最大值i = 4,此时该元素所在队列的长度即为 5 – 1 = 4。
减1说明:
由于正反累加时,当前元素计算2次,例如当i = 4时,对于160这个数,
所在递增序列为{150,160,,,},位置为2
所在反向递增序列为{130,160,,,},位置为2
若取i = 4为分界点,则160所在的队列为{150,160,130},队列长度为 2 + 2 – 1 = 3。
(4)因此需要出队的人数 = 总人数 – 队列长度
针对本示例,应为 8 – (5 – 1) = 4。
代码如下:
int main()
{
int n = 0;
while(cin>>n)
{
int m = 0;
vector dp1(n,1);//记录正向位置
vector dp2(n,1);//记录反向位置
vector vecints;
for(unsigned int i = 0; i < n; i++)
{
cin >> m;
vecints.push_back(m)
}
//计算正向位置
for(unsigned int i = 0; i < n; i++)
{
for(unsigned int j = 0; j < i; j++)
{
if(vecints[j] < vecints[i] && dp1[j] >= dp1[i])
dp1[i] = dp1[j] + 1;
}
}
//反转序列
reverse(vecints.begin(),vecints.end());
//计算反向位置
for(unsigned int i = 0; i < n; i++)
{
for(unsigned int j = 0; j < i; j++)
{
if(vecints[j] < vecints[i] && dp2[j] >= dp2[i])
dp2[i] = dp2[j] + 1;
}
}
//反转位置
reverse(dp2.begin(),dp2.end());
int Max = -1;//记录最大数列
for (unsigned int i = 0; i < n; i++)
{
Max = Max < dp1[i] + dp2[i] ? dp1[i] + dp2[i] : Max;
}
cout << n - Max + 1 << endl;
}
return 0;
}