描述
注意:不允许改变队列元素的先后顺序 且 不要求最高同学左右人数必须相等
数据范围:1≤n≤3000
输入描述:
用例两行数据,第一行是同学的总数 N ,第二行是 N 位同学的身高,以空格隔开
输出描述:
最少需要几位同学出列
示例1
输入:
8 186 186 150 200 160 130 197 200
输出:
4
说明:
由于不允许改变队列元素的先后顺序,所以最终剩下的队列应该为186 200 160 130或150 200 160 130
代码
#include<cstdio>
using namespace std;
int main()
{
/*
N位同学,请出x位,剩下K位
==>K位合唱团
K位合唱团满足:
T_i_lefts < T_i >T_i_rights
*/
// 1.读取数据
int N; //N位同学
int arr[3000];
scanf("%d",&N);
for(int i=0;i<N;i++)
{
scanf("%d",&arr[i]);
}
// 2.动态规划,求每个子序列的最大上升序列
int dp_l_num[3000]; //左侧最大上升子序列
int dp_r_num[3000]; //右侧最大上升子序列
// 2.1 求所有i左侧的最大上升子序列
for(int i=0;i<N;i++)
{
dp_l_num[i]=0; //初始化
// 求当前i的最大上升子序列
for(int j=0;j<i;j++)
{
// 状态转移
if(arr[j]<arr[i] && dp_l_num[i]<dp_l_num[j]+1)
{
dp_l_num[i]=dp_l_num[j]+1;
}
}
}
// 2.2 求所有i右侧的最大下降子序列
for(int i=N-1;i>=0;i--)
{
dp_r_num[i]=0; //初始化
// 求当前i的最大上升子序列
for(int j=N-1;j>i;j--)
{
// 状态转移
if(arr[j]<arr[i] && dp_r_num[i]<dp_r_num[j]+1)
{
dp_r_num[i]=dp_r_num[j]+1;
}
}
}
// 3.在所求各最大子序列中找到最大的,然后总数-该最大数即为要剔除的最少
int max=-1;
int answer=0;
for(int i=0;i<N;i++)
{
if(max<dp_l_num[i]+dp_r_num[i])
{
max=dp_l_num[i]+dp_r_num[i];
}
}
answer=N-max-1;
// 4.输出结果
printf("%d",answer);
}