C++--车厢排序问题
2017-05-02 22:22
281 查看
一列货车共有n节车厢,每个车厢都有自己的编号,编号范围从1~n。给定任意次序的车厢,通过缓冲区将车厢编号按顺序重新排成1~n。共有k个缓冲区。开始时,车厢从入轨进入缓冲轨,经过缓冲轨的重排后,按1~n的顺序进入出轨。缓冲轨按照后进先出方式,编写一个算法,将任意次序的车厢进行重排,输出每个缓冲轨中的车厢编号,使得所用的缓冲区个数(k)最小。
考虑到一个车厢能不能从一个缓冲区(栈),开到后一个缓冲区(栈),设计了两种算法,来处理这个问题。
情况一:不能从一个栈到后一个栈,火车的操作只能是进入缓冲区和从缓冲区到目的地。
这种情况下,我们采取的是贪心的策略。
假设:车厢的序号是0~n的连续正整数。
思路:遍历0~n-1个栈。初始先给0个栈,看是否能解决问题,不能则继续给多一个栈,直到给的栈可以解决问题,就返回这个栈数。
入栈的贪心策略:首先每个栈的栈顶都初始化为0。
入栈原则:
1. 车厢序号比栈顶大或者栈顶为0
2. 优先放在栈顶非0的栈。
3. 优先进入火车序号和栈顶序号绝对值较小的栈。
情况二:能从前一个栈到后一个栈,火车可从任意缓冲区到目的地。
这种情况,没有找到固定的流程一步步实现,我们只能递归从最小栈开始遍历,满足便跳出输出,此时基本上是最优解。
假设:车厢的序号是0~n的连续正整数。
思路:基本思路一样,遍历0~n-1个栈。初始先给0个栈,看是否能解决问题,不能则继续给多一个栈,直到给的栈可以解决问题,就返回这个栈数,但是如何放的方法不同,相当于一种树,遍历每个栈(把初始状态和目标栈也作为其中一个栈),每个栈的元素都有出栈操作,以及出到哪一个栈,不断重复这个操作,直到目标栈被填满输出结果/或者本次操作不满足条件返回上一节点(类似先序遍历)。
简化:一棵树,每个节点是(2,8)
栈个数k为2时,节点的子节点个数为3!个:
不考虑栈间移动 #include<iostream> #include<vector> #include<stack> #include<cstdlib> using namespace std; struct Path{ int train; int from;//0-start int to;//-1-out }; vector<int> start_train; vector< stack<int> > buffer; vector<Path> path; void print(); /************************************************ if any top of stack or start can be popped, then pop it and return true;else return false. fitst parameter is goal train; second one is pointer to the last train in start_train ************************************************/ bool can_out(int,int&); /************************************** parameter is the index of the last train in start_train. This function is to get which stack is best choice to push train in ***************************************/ int get_best(int); int main(){ /*********************************************** step1: read data ***********************************************/ int total_train; cout<<"Input the number of total_train"<<endl; cin>>total_train; cout<<"Input the sequence of start "<<endl; for(int i=0;i<total_train;++i){ int temp; cin>>temp; start_train.push_back(temp); } /*********************************************** step2: simulation ***********************************************/ for(int total_stack=0;total_stack<=total_train-1;++total_stack){ int pointer=start_train.size()-1; for(int i=1;i<=total_stack;++i){ buffer.push_back(stack<int>()); buffer[i-1].push(0);//initialize buffer } int out=1; while(out<=total_train){ if(can_out(out,pointer)){ ++out; } else{ int best_stack=get_best(start_train[pointer]); if(best_stack==-1){ break; } else{ buffer[best_stack].push(start_train[pointer]); Path temp; temp.train=start_train[pointer]; temp.from=0; temp.to=best_stack+1; --pointer; path.push_back(temp); } } } if(out>total_train){ print(); cout<<"It needs "<<total_stack<<" stack(s) "<<endl; break; } path.clear(); buffer.clear(); } system("pause"); return 0; } bool can_out(int goal,int &pointer){ //check buffer first for(int i=0;i<buffer.size();++i){ if(buffer[i].top()==goal){ Path temp; temp.train=buffer[i].top(); temp.from=i+1; temp.to=-1; path.push_back(temp); buffer[i].pop(); return true; } } if(start_train[pointer]==goal){ Path temp; temp.train=start_train[pointer]; temp.from=0; temp.to=-1; path.push_back(temp); --pointer; return true; } return false; } int get_best(int train){ if(buffer.size()==0) return -1; int list[buffer.size()]; for(int i=0;i<buffer.size();++i){ if(buffer[i].top()==0) list[i]=9999999-train; else if(buffer[i].top()<train) list[i]=99999999; else list[i]=buffer[i].top()-train; } int min=list[0]; int index=0; for(int i=0;i<buffer.size();++i){ if(min>list[i]){ min=list[i]; index=i; } } if(list[index]==99999999) return -1; else return index; } void print(){ cout<<endl; for(int i=0;i<path.size();++i){ cout<<path[i].train<<" train move from "; if(path[i].from==0) cout<<"start "; else cout<<"stack "<<path[i].from; cout<<" to "; if(path[i].to==-1) cout<<"destination"<<endl; else cout<<"stack "<<path[i].to<<endl; } } 考虑栈间移动 #include<iostream> #include<stack> #include<vector> using namespace std; int num;//车厢数目 struct as {///记录路径信息 int num; int from; int to; }; vector<as >path; stack<int > s; vector<stack <int> > vs; int stackC = 0;//记录栈个数 void storePath(int num, int from,int to) {//移动时记录 as temp; temp.num = num; temp.from = from; temp.to = to; path.push_back(temp); } void clearPath() { //满足完整排列或者到达某步不满足返回上一层时清除操作 path.pop_back(); } void print() { for (int i = 0;i < path.size();i++) { cout << path[ i].num << "号车厢,在第" << path [i] .from << "个栈,到达" ; if (path[ i].to == -1) { cout << "终点" << endl; } else { cout << path[ i].to << "栈" << endl; } } cout << "一共使用" << stackC << "个栈" << endl; } void nextTrain() { if (s.size() == num) { print(); exit(0); } for (int j = 0;j <= stackC;j++) {//对每个栈 if (path.size() != 0 && j == path[path.size() - 1 ].to) return; if (!vs[ j].empty()) { //判断出栈或者 int top = vs[ j].top(); vs [j] .pop(); if (top==s.size()+1) {//栈顶是否满足出栈条件 //进目标栈 s.push(top); storePath(top,j,-1); //继续排 nextTrain(); if (s.size() == num) { return; } s.pop(); clearPath(); vs [j] .push(top);//不满足还要恢复现场 return; } else {//进栈 进哪一个? j后面所有栈 for (int i = j + 1;i <= stackC;i++) { if ((i - 1 > j&&vs[ i - 1].size() != 0) || i != stackC || vs [i] .size() == 0||top<vs[i] .top()) { vs [i] .push(top); storePath(top, j, i); //继续排 nextTrain(); if (s.size() == num) { return; } clearPath(); vs [i] .pop();//不满足还要恢复现场 //return; } } } vs [j] .push(top);//不满足还要恢复现场 } } } int main() { cout << "输入火车节数:" << endl; cin >> num; cout << "依次输入(从左到右)的车厢编号:" << endl; vs.resize(num); //最大栈num-1 0号栈为初始数据 for (int i = 0;i < num;i++) { int tempc; cin >> tempc; vs [0] .push(tempc); } for (int i = 0;i < num;i++) {//从零个栈开始找,直到遇到满足的路径 stackC = i; nextTrain(); //搜索 } return 0; }
相关文章推荐
- 最简单的C++排序问题
- C++的排序问题。
- 字母排序问题(c++实现)
- C++排序问题
- c++ map的排序问题
- C++排序问题总结
- 常见的C++排序问题
- c++排序的一个问题
- 第 1 章 第 1 题 高级语言的排序问题 C++标准算法实现
- C++中重载和排序问题的简单写法
- C++的数组排序问题。
- c++中vector排序的问题二(转载)
- C++中的vector排序问题
- C++中vector的排序问题
- C++ Queue Example Rearranging RailRoad Cars 火车车厢重排问题
- c++中vector排序的问题二(转载)
- c++中vector排序的问题二(转载)
- C++ Stack Example Rearranging RailRoad Cars 火车车厢重排问题
- C++对10个数选择排序的2个问题分享
- JNI之c/c++返回中文给java 乱码问题以及java数组在c排序