有一队士兵 已知每个士兵个头 想要从中选一些士兵出列 让剩下的士兵向左或向右能看到队首(及左边或右边的士兵个头都< 他)
两次LIS 从左往右 从右往左分别LIS
然后枚举找最少出队人数即可
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define esp 1e-8
using namespace std;
double dp[1111];//左向右LIS
double dpn[1111];//右向左LIS
double ht[1111];//记录士兵身高
int lenup[1111],lendown[1111];//左向右对应位置LIS长度 右向左对应位置LIS长度
int tp;
int dcmp(double x)
{
return x < -esp? -1: x > esp;
}
int main()
{
int n,i,j,mm;
scanf("%d",&n);
for(i = 0; i < n; ++i)
{
scanf("%lf",&ht[i]);
}
tp = 1;
dp[0] = 0;
for(i = 0; i < n; ++i)
{
for(j = tp; j > 0; --j)
{
if(dcmp(ht[i]-dp[j-1]) > 0)
{
if(j == tp) dp[tp++] = ht[i];
else dp[j] = dcmp(ht[i] - dp[j]) < 0? ht[i]: dp[j];
}
}
lenup[i] = tp-1;
}
tp = 1;
dp[n-1] = 0;
for(i = n-1; i >= 0; --i)
{
for(j = tp; j > 0; --j)
{
if(dcmp(ht[i]-dpn[j-1]) > 0)
{
if(j == tp) dpn[tp++] = ht[i];
else dpn[j] = dcmp(ht[i] - dpn[j]) < 0? ht[i]: dpn[j];
}
}
lendown[i] = tp-1;
}
mm = n;
for(i = 0; i < n-1; ++i)//枚举找最少出队人数
{
mm = min(mm,n-(lenup[i]+lendown[i+1]));
}
printf("%d\n",mm);
return 0;
}