L2-014 列车调度 (25 分)
火车站的列车调度铁轨的结构如下图所示。
两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?
输入格式:
输入第一行给出一个整数N (2 ≤ N ≤10
5
),下一行给出从1到N的整数序号的一个重排列。数字间以空格分隔。
输出格式:
在一行中输出可以将输入的列车按序号递减的顺序调离所需要的最少的铁轨条数。
输入样例:
9
8 4 2 5 3 9 1 6 7
输出样例:
4
方法1:运用二分法查找:
火车要递减输出,这需要借助增加轨道和合理安排火车进入入口。运用贪心的思想,结合二分法。将最后一个进入轨道的火车编号存进数组,如果新加入的火车编号大于数组中任意数据则数组容量+1,否则就通过二分法决定新加入的火车替代数组中第几个数据。
二分法:每一次查找与中间值比较,可以确定是否查找成功,不成功当前查找区间将缩小一半,递归查找即可。时间复杂度为:O(log2n)。
二分法查找代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[10],front,end,mid,x,i;
cout<<"请输入已排好序的a数组元素:"<<endl;
for(i=0;i<10;i++){
cin>>a[i];
}
cout<<"请输入待查找的数x:"<<endl;
cin>>x;
front=0;
end=9;
mid=(front+end)/2;
while(front<=end&&a[mid]!=x){
if(a[mid]<x)front=mid+1;
if(a[mid]>x)end=mid-1;
mid=(front+end)/2;
}
if(a[mid]!=x){
cout<<"没找到!"<<endl;
}else{
cout<<"找到了,在第"<<mid+1<<"项里"<<endl;
}
}
题目代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll nl=1e5+5;
ll a[nl];
int main(){
ll n;
cin>>n;
ll i,j;
ll k=0;
for(i=0;i<n;i++){
ll x;
cin>>x;
if(k==0||a[k-1]<x){
a[k]=x;
k++;
}else{
ll l=0,r=k-1;
while(l<=r){//找到距离k最近的大于k的位置
ll mid=(l+r)/2;
if(a[mid]<x){
l=mid+1;
}else{
r=mid-1;
}
}
a[l]=x;
}
}
cout<<k;
}
方法二:运用set内置函数。简单明了。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,k;
scanf("%d",&n);
set<int>st;
for(int i=0;i<n;i++)
{
scanf("%d",&k);
set<int>::iterator it=st.lower_bound(k);//c++ stl容器set成员函数:lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器
if(it==st.end())//c++ stl容器set成员函数:end()--返回指向最后一个元素下一个位置的迭代器
{
st.insert(k);
}
else
{
st.erase(*it);//c++ stl容器set成员函数:erase()--删除集合中的元素
st.insert(k);
}
}
cout<<st.size();
}