解題思路:是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