POJ 1836 Alignment(LIS)

17 篇文章 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值