您的位置:首页 > 编程语言 > C语言/C++

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: