THU数据结构编程作业一:列车调度(Train)
2015-10-17 09:35
411 查看
问题描述
某列车调度站的铁道联接结构如图所示。
其中,A为入口,B为出口,S为中转盲端。所有铁道均为单轨单向式:列车行驶的方向只能是从A到S,再从S到B;另外,不允许超车。因为车厢可在S中驻留,所以它们从B端驶出的次序,可能与从A端驶入的次序不同。不过S的容量有限,同时驻留的车厢不得超过m节。
设某列车由编号依次为{1, 2, …, n}的n节车厢组成。调度员希望知道,按照以上交通规则,这些车厢能否以{a1, a2, …, an}的次序,重新排列后从B端驶出。如果可行,应该以怎样的次序操作?
输入
共两行。
第一行为两个整数n,m。
第二行为以空格分隔的n个整数,保证为{1, 2, …, n}的一个排列,表示待判断可行性的驶出序列{a1,a2,…,an}。
输出
若驶出序列可行,则输出操作序列,其中push表示车厢从A进入S,pop表示车厢从S进入B,每个操作占一行。
若不可行,则输出No。
样例
Example 1
Input
Output
Example 2
Input
Output
限制
1 ≤ n ≤ 1,600,000
0 ≤ m ≤ 1,600,000
时间:2 sec
空间:256 MB
先上源代码:
抽象出题目的含义其实就是栈混洗问题,判断{a1, a2,…..,an} 是否为{1,2,3,……,n}的一个栈混洗。
判断栈混洗,这里最高效的算法就是模拟栈混洗过程。这里我选用了一个数组S(station)来模拟栈,数组S的末尾为栈顶,首位为栈底。因为列车进站的次序编号为 1 到 n 连续的整数,这简化了模拟过程。从出站的立车次序出发,依次考虑出站列车编号。同时我使用了三个整数下标来模拟指针,每移动一位下标变化一位。
另外,我在栈底和进站数组的末尾分别加了一个元素作为哨兵,该元素要比原序列最大的元素大方便后来的比较判断操作。
程序主题部分应该是循环部分,外围一个大循环,内部两个分别用于入栈和出栈的循环。外围循环设置一个标志位标志循环是否结束,只要内部的任意一个循环进行了操作就说明循环没有结束,只有当没有入栈和出栈操作后循环才结束。
对于内部的入栈操作循环,因为入栈序列有序,对于出栈的某一个元素,从头考虑入栈序列,当入栈序列元素小于或等于该出栈序列中的元素就将入栈序列元素压入栈中。若待入栈元素大于出栈序列元素就结束循环,进入出栈操作循环,判断栈顶元素与出栈祖列元素是否相等,相等就出栈,同时经栈指针下移一位继续比较,直到栈顶元素与出栈元素不等就结束循环。
最终通过记录的出栈元素个数来判断出栈元素序列是否为入栈元素序列的一个栈混洗。
某列车调度站的铁道联接结构如图所示。
其中,A为入口,B为出口,S为中转盲端。所有铁道均为单轨单向式:列车行驶的方向只能是从A到S,再从S到B;另外,不允许超车。因为车厢可在S中驻留,所以它们从B端驶出的次序,可能与从A端驶入的次序不同。不过S的容量有限,同时驻留的车厢不得超过m节。
设某列车由编号依次为{1, 2, …, n}的n节车厢组成。调度员希望知道,按照以上交通规则,这些车厢能否以{a1, a2, …, an}的次序,重新排列后从B端驶出。如果可行,应该以怎样的次序操作?
输入
共两行。
第一行为两个整数n,m。
第二行为以空格分隔的n个整数,保证为{1, 2, …, n}的一个排列,表示待判断可行性的驶出序列{a1,a2,…,an}。
输出
若驶出序列可行,则输出操作序列,其中push表示车厢从A进入S,pop表示车厢从S进入B,每个操作占一行。
若不可行,则输出No。
样例
Example 1
Input
5 2 1 2 3 5 4
Output
push pop push pop push pop push push pop pop
Example 2
Input
5 5 3 1 2 4 5
Output
No
限制
1 ≤ n ≤ 1,600,000
0 ≤ m ≤ 1,600,000
时间:2 sec
空间:256 MB
先上源代码:
#include<cstdio> #include<cstdlib> //fast io /********************* * setvbuf(FILE *stream , char *buf, int type, unsigned size) * type: * _IOFBF: read from stream when buffer is empty, or write to stream when buffer is full * _IOLBF: read from or write to stream by lines * _IONBF: read from or write to stream without buffer * size: * size of buffer (bytes) * * *********************/ const size_t SZ = 1 << 20; struct fastio{ char inbuf[SZ]; char outbuf[SZ]; fastio(){ setvbuf(stdin, inbuf, _IOFBF, SZ); setvbuf(stdout, outbuf, _IOFBF, SZ); } }io; const size_t max_number = 1600010;//maximum size is 1600000 int A[max_number];//Entering line A int B[max_number];//Leaving line B int S[max_number];//Station S bool Operation[2*max_number];//store operation historis, TRUE for push(), FALSE for pop() int main(){ //redirecte io to file #ifndef _OJ_ freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); #endif long line_size, station_size;//number of trains and the maximum trains station can contain scanf("%ld %ld", &line_size, &station_size); for(int i = 0; i < line_size; ++i) scanf("%d", &B[i]); for(int i = 0; i < line_size; i++) A[i] = i + 1; A[line_size] = line_size + 1;//set a sentry S[0] = line_size + 1; //three simulated pointers pointing to three arraies respectively size_t pointer_A(0), pointer_B(0), pointer_S(0); size_t op_size(0);//operation times bool end = false; //flag for the loop ending while(end = !end){ //push numbers into stack until the next is larger than the given one while(pointer_S < station_size && B[pointer_B] >= A[pointer_A]){ S[++pointer_S] = A[pointer_A++];//move pointer Operation[op_size++] = true; //recorder the operation end = false; } //pop from stack until the next is unequal to the given one while(S[pointer_S] == B[pointer_B]){ --pointer_S; ++pointer_B;//move pointer Operation[op_size++] = false;//record the operation end = false; } } //pointer of B moving to the end means the successful traversal if(pointer_B == line_size) for(int i = 0; i < op_size; ++i) if(Operation[i]) printf("push\n"); else printf("pop\n"); else printf("No\n"); return 0; }
抽象出题目的含义其实就是栈混洗问题,判断{a1, a2,…..,an} 是否为{1,2,3,……,n}的一个栈混洗。
判断栈混洗,这里最高效的算法就是模拟栈混洗过程。这里我选用了一个数组S(station)来模拟栈,数组S的末尾为栈顶,首位为栈底。因为列车进站的次序编号为 1 到 n 连续的整数,这简化了模拟过程。从出站的立车次序出发,依次考虑出站列车编号。同时我使用了三个整数下标来模拟指针,每移动一位下标变化一位。
另外,我在栈底和进站数组的末尾分别加了一个元素作为哨兵,该元素要比原序列最大的元素大方便后来的比较判断操作。
程序主题部分应该是循环部分,外围一个大循环,内部两个分别用于入栈和出栈的循环。外围循环设置一个标志位标志循环是否结束,只要内部的任意一个循环进行了操作就说明循环没有结束,只有当没有入栈和出栈操作后循环才结束。
对于内部的入栈操作循环,因为入栈序列有序,对于出栈的某一个元素,从头考虑入栈序列,当入栈序列元素小于或等于该出栈序列中的元素就将入栈序列元素压入栈中。若待入栈元素大于出栈序列元素就结束循环,进入出栈操作循环,判断栈顶元素与出栈祖列元素是否相等,相等就出栈,同时经栈指针下移一位继续比较,直到栈顶元素与出栈元素不等就结束循环。
最终通过记录的出栈元素个数来判断出栈元素序列是否为入栈元素序列的一个栈混洗。
相关文章推荐
- Language of FatMouse(trie树)
- Python基本数据结构 习题及源码
- 数据结构基础7_链队的实现
- 数据结构之链表(链接)
- 堆排序
- 数据结构实验之栈六:下一较大值(二)【OJ-3333】【自己写的封装的栈代码】
- hbase系统架构及数据结构
- 【数据结构与算法分析】1.1 找出N个数字中第K大的数
- 数据结构栈应用之进制转换
- What Are You Talking About(trie树或map)
- opencv学习笔记(十三)——数据结构
- 数据结构c字符串操作语言版本
- 《数据结构与算法分析-C语言描述》中的字谜问题
- spfa 模板
- 实验数据结构——KMP算法Test.ming
- Hbase 系统架构与数据结构
- SQL查询优化——数据结构设计
- 数据结构基础6_链栈的实现
- 【ShancoLove】带你看数据结构——第七课:树的基本概念
- 重温数据结构——图的遍历