poj 1836 简单的dp
一些军人排队,给了你一个数组,告诉你他们的身高,问最少踢出多少个人,可以保证整个队伍每个人都能至少看到他一边人?也就是中间的一个人最高,两边的人逐渐变矮就可以了。
具体做法就是从头到尾一个个枚举,假设当前的点就是最高点。在分别对两边进行dp求最大升序子序列并加起来,最大的那个值就是了。注意中间可能有两个一样高的人都是最高的,特判一下就好了~
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
double a[1010],b[1010],c[1010],ans[1010];
int main()
{
// freopen("data.in","r",stdin);
int n,i,j,p,ans1,ans2,min;
scanf("%d",&n);
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
memset(ans,0,sizeof(ans));
for(i=0;i<n;++i)
scanf("%lf",&a[i]);
for(p=0;p<n;++p)
{
ans1=ans2=1;
b[ans1]=a[0];
c[ans2]=a[n-1];
for(i=1;i<p;++i)
{
if(a[i]>b[ans1])
b[++ans1]=a[i];
else
{
int k=lower_bound(b+1,b+ans1,a[i])-b;
b[k]=a[i];
}
}
for(i=n-2;i>p;--i)
{
if(a[i]>c[ans2])
c[++ans2]=a[i];
else
{
int k=lower_bound(c+1,c+ans2,a[i])-c;
c[k]=a[i];
}
}
if(p==0) ans[p]=a[p]>c[ans2]?ans2+1:ans2;
else if(p==n-1) ans[p]=a[p]>b[ans1]?ans1+1:ans1;
else ans[p]=(a[p]>b[ans1]||a[p]>c[ans2])?ans1+ans2+1:ans1+ans2;
}
min=2000;
for(i=0;i<n;++i)
if(n-ans[i]<min)
min=n-ans[i];
if(n==2) printf("0\n");
else printf("%d\n",min);
return 0;
}