前言
通过这个问题的解答,思考,感觉对递归掌握更深了一点,很棒的一道题。代码有详细解释,互相学习~
铁路调度问题 – 递归 – 栈 – 笔试题目
左边停了N个车厢,N个车厢依次编号为1-N。现希望通过中间的Y字型铁轨。将所有车厢拉到右边,所有车厢不允许走重复的路。
请列出所有列车到右边铁路后,右边列车所有可能的排法
注意并非全排列
#include <iostream>
#include <stdlib.h>
using namespace std;
/*
问题:C语言编程。Y字形铁路如下图:
铁路调度问题
---》 ---》
| |
| |
| |
———
左边停了N个车厢,N个车厢依次编号为1-N。现希望通过中间的Y字型铁轨。将所有车厢拉到右边,所有车厢不允许走重复的路。
请列出所有列车到右边铁路后,右边列车所有可能的排法
解析:
1.可以将Y字型中间看作一个栈
2.每次都有只有两种处理方式:出栈/入栈。这是一种典型的递归问题
算法:
根据解析可以用两重递归,入栈与出栈分别为一个递归。
条件:
-- 进栈递归跳出条件为最后一个元素进栈,本题目可以用左侧编号=0表示,因为
-- 出栈递归跳出条件为栈空
*/
// 定义一个简单的栈类
class myStack{
private:
int top; /* 栈顶的下标 */
int *data; /* 栈空间 */
public:
myStack( int n ){
/* n为栈的大小 */
top = -1;
data = new int[n];
}
~myStack(){
delete [] data;
}
public:
/* 三个操作函数 省略容错处理(解本题目可省略) */
void push(int q){
top ++ ;
data[top] = q;
}
bool isEmpty(){
return top==-1?true:false;
}
int pop(){
return data[ top -- ];
}
};
/* __process递归函数声明,提供process调用,再process下面定义
参数都是记录当前处理的状态:
mystack ---- Y字型中间栈的状态
pos ----- 左侧待操作的车厢编号
path[] ----- 记录右侧轨道状态的数组,存储编号排列
curp ----- 记录右侧车厢数目
*/
void __process( myStack &mystack , int pos , int path[] , int curp );
/* process函数,输入参数为左侧待操作车厢数目 */
void process( int N ){
myStack mystack(N); /* 模拟Y字型中间栈 */
int path[N]; /* 存放右侧车厢编号排列 */
cout << "所有输出序列为:"<< endl;
__process( mystack , N , path , 0 ); /* 第一次操作 */
}
/*__process 函数 定义*/
void __process( myStack &mystack , int pos , int path[] , int curp ){
/* 每次操作都为 -- 两个选择,入栈以及出栈 */
// 1.入栈
if( pos > 0 ) { // 入栈条件,左侧有车厢,即pos>0
mystack.push( pos );
__process(mystack , pos-1 , path , curp);
// 进行下一次抉择
mystack.pop(); // 恢复原状
}
// 2.出栈
if(!mystack.isEmpty()) {
int m = mystack.pop(); //把当前车厢出栈
path[curp] = m; // 出栈车厢放在右边
__process(mystack , pos , path , curp + 1 );
// 进行下一次抉择
mystack.push(m); // 恢复原状
}
// 3.最终 pos == 0 左侧无车厢 && isEmpty 栈空,栈中无车厢 , 此时右侧调度完成,输出结果
if( pos == 0 && mystack.isEmpty() ){
for( int i = curp-1 ; i >= 0 ; i-- ){
// 此时curp为 N ,车厢按照从左到右输出,最左侧为path最后一个元素
cout << path[i] << " " ;
}
cout << endl;
}
}
int main(){
int n ;
cout << "左侧车厢数量 : " ;
cin >> n;
process(n);
}