L2-014 列车调度 (25 分)

L2-014

两端分别是一条入口(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
本来一看到这题我以为是个优先队列模拟(意味着每个平行的铁轨最多同时存放一辆车)但是发现样例不对,然后经过大神的点播我才知道可以同时存放多辆。因此,这题便可以是一个查找下降子序列的个数的题目了。为什么呢?只有同一铁轨的存放的车辆按从大到小的顺序排放,才能使得同时占用的铁轨数量最少。–当然,这题还有一个坑:为了使得同一铁轨的火车数量最多,相当于下降子序列的下降速度更慢,我们得找最接近当前读入的那个数的铁轨来存放,这样效益才最大。因此,用lower_bound函数和set这种自动去重排序的就很方便了。

#include<bits/stdc++.h>
using namespace std;
set<int> s;
int a[105000];
int main() {
	int n;
	set<int>::iterator j;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i]; 
	}//读入
	for (int i = 1; i <= n; i ++) {//遍历一遍来插入相应的位置
		j = s.lower_bound(a[i]);//set里面的每个值相当于每条铁轨上的最小的车,尾随的车不能小于他们,否则要重新建一条铁轨
		if (j == s.end()) {//相当于没有比它更小的,无法尾随,那就建一条
			s.insert(a[i]);
		}
		else {
			s.erase(j);//有比它更小的,替换它,变成更小的
			s.insert(a[i]);
		}
	}
	cout << s.size() << endl;//这样set的大小就是铁轨数量
	return 0;
}

顺便也说说如果同时只能放一辆的情况:是个优先队列模拟了,如果队首的车子和当前需要输出的车子不匹配,就再进入一辆到优先队列里自动排序,再进行队首匹配,直到匹配,就移除队首,接上下一辆需要输出的车子。

#include<bits/stdc++.h>
using namespace std;
priority_queue<int> q;
int max(int a, int b) {//比大小
	if (a > b) {
		return a;
	}
	else {
		return b;
	}
}
int a[105000], b[105000];
int main() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		b[i] = i;
	}//原始数据入a数组,b数组为输出样子
	int xa = 1, xb = n;
	int maxn = 0;
	q.push(a[xa]);
	xa++;//先推入一个防止空
	while (!q.empty()) {//没输出完
		if (q.top() == b[xb]) {//队首匹配成功
			xb--;//下一辆需要输出的车子
			q.pop();//移除队首
			maxn = max(maxn, q.size());//当前占用铁轨数量
		}
		else {//不匹配
			maxn = max(maxn, q.size());
			q.push(a[xa]);//进入下一辆
			xa++;
		}
	}
	cout << maxn << endl;//整个过程中出现的最大值
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值