您的位置:首页 > 理论基础 > 数据结构算法

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

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 连续的整数,这简化了模拟过程。从出站的立车次序出发,依次考虑出站列车编号。同时我使用了三个整数下标来模拟指针,每移动一位下标变化一位。

另外,我在栈底和进站数组的末尾分别加了一个元素作为哨兵,该元素要比原序列最大的元素大方便后来的比较判断操作。

程序主题部分应该是循环部分,外围一个大循环,内部两个分别用于入栈和出栈的循环。外围循环设置一个标志位标志循环是否结束,只要内部的任意一个循环进行了操作就说明循环没有结束,只有当没有入栈和出栈操作后循环才结束。

对于内部的入栈操作循环,因为入栈序列有序,对于出栈的某一个元素,从头考虑入栈序列,当入栈序列元素小于或等于该出栈序列中的元素就将入栈序列元素压入栈中。若待入栈元素大于出栈序列元素就结束循环,进入出栈操作循环,判断栈顶元素与出栈祖列元素是否相等,相等就出栈,同时经栈指针下移一位继续比较,直到栈顶元素与出栈元素不等就结束循环。

最终通过记录的出栈元素个数来判断出栈元素序列是否为入栈元素序列的一个栈混洗。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: