解题思路:是POJ2533的扩展题。
题意不难,令到原队列的最少士兵出列后,使得新队列任意一个士兵都能看到左边或者右边的无穷远处。就是使新队列呈三角形分布就对了。
但这里有一个陷阱,看了一些别人的解题报告说“任一士兵旁边不能存在等高的士兵”,然后又举了一个例子说注意
3
5 5 5
的情况,我没看他们的程序,不知道他们是不是把这些例子特殊处理了,但完全没必要,因为“允许处于三角形顶部的两个士兵等高”,图形化就是如下图:
其实蓝色士兵的身高和红色士兵的身高是完全没有关系的。
要求最少出列数,就是留队士兵人数最大,如图,即左边的递增序列人数和右边的递减序列人数之和最大
因而可转化为求“最长不降子序列”和“最长不升子序列”问题
注意:等高的也会遮住视线!!!!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const double inf = 3.0;
int pre[1111],back[1111];
double dp[1111],a[1111];
void print(int n)
{
int i;
for(i=1;i<=n;i++) cout<<pre[i]<<" ";
cout<<endl;
for(i=1;i<=n;i++) cout<<back[i]<<" ";
cout<<endl;
}
int main()
{
int i,j,n,ans;
int p1,p2,p;
cin>>n;
for(i=1;i<=n;i++) cin>>a[i];
fill(dp,dp+n,inf);
for(i=1;i<=n;i++) {
p = lower_bound(dp,dp+n,a[i])-dp;
dp[p] = a[i];
pre[i] = max(pre[i-1],p+1);
}
fill(dp,dp+n,inf);
ans=0;
for(i=n;i;i--) {
p = lower_bound(dp,dp+n,a[i])-dp;
dp[p] = a[i];
back[i] = max(back[i+1],p+1);
}
// print(n);
for(i=1;i<=n;i++) {
for(j=i+1;j<=n;j++) {
ans=max(ans,pre[i]+back[j]);
}
}
cout<<n-ans<<endl;
return 0;
}
Write a program that, knowing the height of each soldier, determines the minimum number of soldiers which have to get out of line.
There are some restrictions:
• 2 <= n <= 1000
• the height are floating numbers from the interval [0.5, 2.5]
8 1.86 1.86 1.30621 2 1.4 1 1.97 2.2Sample Output
4