列车调度
列车调度
题目详见: https://dsa.cs.tsinghua.edu.cn/oj/problem.shtml?id=1145
描述
某列车调度站的铁道联接结构如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
思路
这道题其实按我理解,很类似出栈序列的合法性,当然算法很不一样。我说类似判断类似出栈合法性是因为第一次看到题的时候,以为是给你一个乱序序列(12354),让你借助栈,以升序(12345)序列输出。
然而并不是啊!!!所以一直看不懂样例2的no是怎么来的。
纠结了好久,网上看了之后才发现问题所在。然后也发现,这种问题其实叫"栈混洗问题"。
解决方法呢主要是两个一维数组,一个int栈。一维数组seq用来存储待检验的序列。另一个一维数组ans用来存储操作(因为该题如果结果为“No”是不需要输出操作的,所以要先把操作存储,然后根据最后结果判断是否输出),1代表“push",2代表"pop"。
首先搞清楚输出"No"的判断条件:
case1:栈容量溢出。
case2:栈顶元素大于待检测序列的第一位.
然后在n个循环中和seq的元素依次进行比对,若seq的元素大于循环i,那么把i入栈,ans数组增加元素1,直到他俩相等。
如果栈顶元素等于当前seq[i]的元素,那么pop,然后ans数组增加元素0.
代码
如有错误,请多指正
#include <iostream>
using namespace std;
/**********************************
输出NO:
case1:栈容量溢出
case2:栈顶元素大于待检测序列的第一位
**********************************/
template<typename T>
class stack
{
private:
T* data;
T top;
int maxsize;
public:
stack ( int _max )
{
maxsize = _max;
data = new T[maxsize];
top = -1;
}
void expand()
{
int newsize = maxsize * 2;
T *newdata = new T[newsize];
for ( int i = 0; i < maxsize; i++ )
newdata[i] = data[i];
maxsize = maxsize * 2;
data = newdata;
}
void push ( T x )
{
if ( top == maxsize - 1 )
expand();
data[++top] = x;
}
void pop ()
{
if ( top > 0 )
{
top--;
}
}
bool empty()
{
return top == -1 ? true : false;
}
T gettop()
{
if ( top != -1 )
return data[top];
return -1;
}
int size()
{
return top + 1;
}
};
int main()
{
int m;//序列个数
int n;//栈容量
int j = 0;
int k = 0;//ans的下标
cin >> m >> n;
int seq[m];
int ans[2*m] ;//操作最大为2m
stack<int> s ( 100 );
for ( int i = 1; i < m+1; i++ )
scanf ( "%d", &seq[i] );
for ( int i = 1; i < m+1; i++ )
{
//case2
if ( seq[i] < s.gettop() && !s.empty())
{
printf ( "No\n" );
return 0;
}
if ( seq[i] > j )
{
while ( seq[i] != j )
{
s.push ( ++j );
ans[k++] = 1;
}
}
//case1
if ( s.size() > m )
{
printf ( "No\n" );
return 0;
}
if ( s.gettop() == seq[i] )
{
s.pop();
ans[k++] = 0;
}
}
for(int i= 0;i<k;i++)
{
if(ans[i])
printf("push\n");
else
printf("pop\n");
}
return 0;
}
本文来自博客园,作者:klaus08,转载请注明原文链接:https://www.cnblogs.com/klaus08/p/15105042.html