列车调度-栈混洗

来源:互联网 发布:mac如何缩小照片kb 编辑:程序博客网 时间:2024/04/29 16:08

题目

列车调度

描述

某列车调度站的铁道联接结构如Figure 1所示。

其中,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


栈的实现

基于上次的栈数据结构的良好实现,不妨直接引用,从而把更多的精力放在栈混洗的算法实现以及优化上面。
Stack在C++的实现。

template <typename T> class Stack{private:// 私有成员变量    T* elem;     int _top; public:// 构造函数与析构函数    Stack(int s=100, T sentinel=0)    { elem = new T[s+1]; _top = 0; elem[0] = sentinel; }    ~Stack() { if(elem) delete[] elem; }// 操作接口    bool empty() { return !_top; }    int size() { return _top; }    void push(T value) { elem[++_top] = value; }    T pop() { return elem[(empty()) ? _top : _top--]; }//空栈时退化成top()    T& top() { return elem[_top]; }};

数据分析

难道真的需要三个栈来模拟栈混洗?

答案是否定的,出口B只是依次检查下一个元素应该是什么,入口A只是把一个个元素压入中转栈S中,这两个的简单的操作都不必用上栈结构,栈的特性是FILO,也就是先进后出,只有同时涉及到两个方面的还得是FILO操作的时候,才必须用上栈。目前只是中转栈S是符合这个要求,那中转栈S是必须用栈结构来实现的,那么入口序列A和出口序列B呢?

用线性结构来储存序列?

一般说到一个序列,首先就是想到线性结构,线性结构包括向量链表,那么这里的入口序列A和出口序列B都需要用一个向量或链表来储存吗?答案又是否定的,无论是A还是B,对它们里面的每个元素,操作次数都是1,也就是说,只要查询一次,数据就可以丢弃了,也可以不必储存。再来看看A和B的区别,A是一个递增的等差序列,B则是一个乱序的序列,那么B里面的每一项和下一项都没有任何逻辑联系,于是B是需要用一个线性结构来储存的,则入口的序列却大可不必。

对于有规律的一次性序列,可以用变量!

入口序列A是一个单调递增的等差序列An=n+1,前一项和后一项的关系是An=An1+1,用C++的方式表示的话,简单的一个A++就可以得到后项了,我说的不是单纯递增的一次性序列才可以用一个变量,而是所有有规律可寻的一次性的序列都是用少数的变量来存储,使得空间复杂度进一步的缩减。

算法

int main() {    int n, m;    scanf("%d %d\n", &n, &m);       // 采用手动解析文本的方式输入数据    char* txt = new char[n << 4];    int len = fread(txt, sizeof(char), n << 4, stdin);    txt[len] = '\0';    int A = 1; // 入口车厢序列初始化,A为变量    int* B = new int[n]; data_analyse(txt, B); // 出口车厢序列初始化,B为数组    Stack<int> S(m); //中转车厢序列初始化,S为栈    //txt可再利用为输出数据的储存空间    char* p = txt;    for(int i = 0; i < n; i++){        while(S.top() < B[i]){            S.push(A++);            p = output(p, "push\n");        }        if(m < S.size()){                        output((p = txt), "No\n");            break;        }        if(S.pop() == B[i]){            p = output(p, "pop\n");        }        else{            output((p = txt), "No\n");            break;        }    }    printf("%s", txt);      return 0; }
1 0