是POJ2533的扩展题。题意不难,令到原队列的最少士兵出列后,使得新队列任意一个士兵都能看到左边或者右边的无穷远处。就是使新队列呈三角形分布就对了。士兵的排列就是如附件所示所示:图片中的蓝色士兵的身高和红色士兵的身高是完全没有关系的。
要求最少出列数,就是留队士兵人数最大,如图:
即左边的递增序列人数和右边的递减序列人数之和最大因而可转化为求“最长不降子序列”和“最长不升子序列”问题。进一步转化为从头部求出最长不下降子序列与从尾部求出最长不下降子序列即可,分别求出二者的大小,二者之和的最大值就是满足图中所示的最大数目,最后用队列长度减去二者之和的最大值就是我们所求的出列的士兵个数。
转自:
http://cavenkaka.iteye.com/blog/1542421
#include <stdio.h>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX_N (1000+1)
int n;
int dp[MAX_N],dpdown[MAX_N];
double N[MAX_N];
int get_lcis_up()
{
int maxj;
dp[0] = 0;
for(int i=1;i<=n;i++)
{
maxj = 0;
for(int j=1;j<i;j++)
{
if( N[i] >N[j] && dp[j] > maxj)
{
maxj = dp[j];
}
}
dp[i] = maxj +1;
//printf("dp[%d] =%d\n",i,dp[i]);
}
dpdown[n]= 1;
for(int i=n-1;i>=1;i--)
{
maxj = 0;
for(int j=i+1;j<=n;j++)
{
if( N[i] > N[j] && dpdown[j] > maxj)
{
maxj = dpdown[j];
}
}
dpdown[i] = maxj +1;
//printf("dpdown[%d]=%d\n",i,dpdown[i]);
}
maxj=0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
if(dp[i]+dpdown[j]>maxj)
maxj = dp[i] + dpdown[j];
}
return maxj ;
}
int main()
{
while(cin>>n)
{
for(int i=1;i<=n;i++)
{
cin>>N[i];
}
int lcis = get_lcis_up();
cout<<n-lcis<<endl;
}
}