2017天梯赛决赛模拟赛(14-15-16)(重现)

  1. 编程题 15小题,共计290分
290分
7 列车调度   (25分)

火车站的列车调度铁轨的结构如下图所示。

两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?

输入格式:

输入第一行给出一个整数N (2 ≤\leN≤105\le 10^5105),下一行给出从1到N的整数序号的一个重排列。数字间以空格分隔。

输出格式:

在一行中输出可以将输入的列车按序号递减的顺序调离所需要的最少的铁轨条数。

输入样例:

9
8 4 2 5 3 9 1 6 7

输出样例:

4
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int a[100005];
int cnt;
int rail[100005];
void Binary_search(int x)
{
    int l,r,mid;
    l = 1;
    r = cnt;
    while(l<r)
    {
        mid = l+(r-l)/2;
        if(rail[mid]>x)r = mid;
        else if(rail[mid]<x) l = mid+1;
    }
    rail[r] = x;
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    cin>>a[i];
   cnt = 0;
    for(int i=1;i<=n;i++)
    {
        if(cnt==0)
        {
            rail[++cnt] = a[i];
        }
        else
        {
            if(rail[cnt]<a[i])
            {
                rail[++cnt] = a[i];
            }
            else
            Binary_search(a[i]);
        }
    }
    cout<<cnt<<endl;
    return 0;
}

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int a[100005];
int cnt;
int rail[100005];
void Binary_search(int x)
{
    int l,r,mid;
    l = 1;
    r = cnt;
    while(l<r)
    {
        mid = l+(r-l)/2;
        if(rail[mid]>x)r = mid;
        else if(rail[mid]<x) l = mid+1;
    }
    rail[r] = x;
}
int main()
{
    int n,x;
    cin>>n;
    set<int>q;
    q.clear();
    set<int>::iterator it;
    for(int i=0;i<n;i++)
    {
            scanf("%d",&x);
            if(q.empty())
            {
            q.insert(x);
            }
            else
            {
                it =q.lower_bound(x);
                if(it==q.end())
                q.insert(x);
                else
                {
                    q.erase(it);
                    q.insert(x);
                }
            }


    }cout<<q.size()<<endl;
    return 0;
}

最少拦截系统

Time Limit: 1000MS Memory Limit: 65536KB

Problem Description

 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹.
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.
 
 

Input

 输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔)

Output

 对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统.
 

Example Input

8 389 207 155 300 299 170 158 65

Example Output

2

Hint

Author

/*
   功能Function Description:  HDOJ-1257 求最长 不降 子序列
   开发环境Environment:       DEV C++ 4.9.9.1
   作者Author:               可笑痴狂
   日期Date:                 20120723
   备注Notes:
        解题思路:
        应该求最长 不降 子序列。这样的长度才是 最少需要的 套数,因为这个序列中的任何两个导弹
        都不能共用一个拦截系统   ,而且其余的导弹 都能和这个最长序列中的某个导弹分为同一组。

*/

#include<cstdio>

int main()
{
    int n,i,j,num,h[100002],max[100002];
    scanf("%d",&n);
        num=0;
        for(i=0;i<n;++i)
        {
            scanf("%d",&h[i]);
            max[i]=1;
        }
        for(i=1;i<n;++i)
            for(j=0;j<i;++j)
            {
                if(h[j]<=h[i]&&max[j]+1>max[i])
                    max[i]=max[j]+1;
                if(num<max[i])
                    num=max[i];
            }
        printf("%d\n",num);

    return 0;
}

这两个题目是一样的,但后一题的代码却水不过第一题,说明后一题的代码效率比较低
具体解释要用到数论中的Dilworth定理(最小反链划分 == 最长链)即最少的下降序列个数就等于整个序列最长上升子序列的长度
推荐博客:http://blog.csdn.net/challengerrumble/article/details/51939356