关闭

POJ 1836 Alignment(LIS)

394人阅读 评论(0) 收藏 举报
分类:

Description
令到原队列的最少士兵出列后,使得新队列任意一个士兵都能看到左边或者右边的无穷远处
Input
第一行为士兵个数n(2<=n<=1000),第二行为每个士兵的身高h(0.5<=h<=2.5)
Output
输出最少出列士兵数
Sample Input
8
1.86 1.86 1.30621 2 1.4 1 1.97 2.2
Sample Output
4
Solution
题意即为求使数列程先递增后递减的形式需要去掉的数字个数,当然也可以直接递减或者只递减不递增,双向lis后,求出以某个士兵作为队伍最高点时其左边递增数列人数与其右边递减数列人数之和最大值即为出列最少士兵后的队伍,用队伍总人数减去求出的最大值即为出列士兵最少人数
Code

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define INF (1<<29)
#define maxn 1010
struct node
{
    int up,down;
}DP[maxn];//DP[i].up表示以第i个士兵为最高点时其左方递增序列人数,DP{i].down表示以第i个士兵为最高点时其右方递减序列人数 
int n;
float h[maxn];
float dp[maxn];
void LIS1() 
{
    for(int i=0;i<n;i++)
        dp[i]=10.0;
    for(int i=0;i<n;i++)
    {
        int t=lower_bound(dp+1,dp+n+1,h[i])-dp;
        DP[i].up=t;
        dp[t]=h[i];
    }
}
void LIS2()
{
    for(int i=0;i<n;i++)
        dp[i]=10.0;
    for(int i=n-1;i>=0;i--)
    {
        int t=lower_bound(dp+1,dp+n+1,h[i])-dp;
        DP[i].down=t;
        dp[t]=h[i];
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<n;i++)
            scanf("%f",&h[i]);
        memset(DP,0,sizeof(DP));//初始化 
        LIS1();//求正向递增数列 
        LIS2();//求反向递增数列 
        int max=0;
        for(int i=0;i<n-1;i++)//遍历所有点 
            for(int j=i+1;j<n;j++)
                if(max<DP[i].up+DP[j].down)//更新队伍最后人数最大值 
                    max=DP[i].up+DP[j].down;
        printf("%d\n",n-max);//队伍总人数减去队伍人数最大值即为出列士兵最小值 
    }
    return 0;
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:391359次
    • 积分:20184
    • 等级:
    • 排名:第426名
    • 原创:1692篇
    • 转载:0篇
    • 译文:0篇
    • 评论:64条
    最新评论