火车车厢重排问题

问题描写叙述:一列货运火车从出发站出发时火车上一共同拥有n节车厢,编号各自是1到n。运货的各节车厢是在入轨上时是随机的顺序,火车头在出轨处,如今要将各节车厢按编号从大到小挂到车头上。当中在入轨与出轨之间有k条缓冲铁轨,将通过缓冲铁轨完毕本次的火车车厢的重排。

     详细规则:

一、车厢从入轨的前部(即右端)仅仅能够移动到一个缓冲铁轨的顶端或出轨的右端。

二、缓冲铁轨的顶端的车厢仅仅能够移动到出轨的最左端

三、车厢不能从一个缓冲铁轨移动到还有一个缓冲铁轨或者再移动到入轨

四、车厢移动到出轨的最左端(即火车头端)后不能再移动


解决步骤:

一、     从入轨端開始移除最右边的车厢假设该车厢正好能够挂在出轨端则直接移到入轨端。然后再在缓冲铁轨中查找是否有接到出轨上的车厢如有则移出如无则開始步骤四。否则先在每条缓冲铁轨中查找。

二、     假设能找到一条缓冲铁轨顶端的车厢编号正好比它大并且和它最接近则移动到该条缓冲铁轨上

三、     假设每一条有车厢的缓冲铁轨的顶端车厢编号都比它小,则再查找有没有空的缓冲铁轨假设有则移动到缓冲铁轨上,否则返回false。

四、     继续開始从入轨端移除最右端的车厢而且開始反复步骤一。

 

        应用的数据结构:

        因为对于每个缓冲铁轨来说都是LIFO后进先出的特点所以能够考虑採用栈的数据结构。

详细实现代码及结果例如以下:

#include<iostream>
#include<vector>
#include<stack>
#include<deque>
#include<iterator>
#include<algorithm>
using namespace std;


//辅函数:更新缓冲铁轨上的min_buf、min_tra
void updata(vector<stack<int>> & tracks_buf,int & min_buf,int & min_tra)
{
	for (int i = 0;i<tracks_buf.size();i++)
	{
		if(!tracks_buf[i].empty() && min_buf>tracks_buf[i].top())
		{
			min_buf = tracks_buf[i].top();
			min_tra = i;
		}
	}
}
//辅函数:将车厢移到缓冲铁轨上
bool trans(int n,int d,vector<stack<int>> & tracks_buf,int & min_buf,int & min_tra)
{
	//先查找最优缓冲铁轨
	int min_gap = n+1;//d与个缓冲铁轨顶端上大于的车厢与d之间的最小间隔
	int prefer_track = -1;//最优铁轨
	for (int i = 0;i<tracks_buf.size();i++)
	{
		if (!tracks_buf[i].empty() && tracks_buf[i].top()>d && (tracks_buf[i].top()-d)<min_gap)
		{
			min_gap = tracks_buf[i].top()-d;
			prefer_track = i;
		}
	}
	if(-1!=prefer_track)//找到最优缓冲铁轨
	{
		tracks_buf[prefer_track].push(d);
		updata(tracks_buf,min_buf,min_tra);
		return true;
	}
	else
	{
		//再查找是否存在空铁轨
		for (int i = 0;i<tracks_buf.size();i++)
		{
			if(tracks_buf[i].empty())
			{
				tracks_buf[i].push(d);
				updata(tracks_buf,min_buf,min_tra);
				return true;
			}
		}
		//否则返回false;
		return false;
	}
}

/*  火车车厢重排问题
*	datas:火车车厢在入轨上时的序列
*   n : 火车车厢的总节数
*	k :缓冲铁轨的条数
*/
//主要函数
bool fun(vector<int> &datas,deque<int> & results,int n,int k)
{
	int min_buf = n+1;//缓冲铁轨上最小的车厢号
	int min_tra = 0;//最小的车厢所在的缓冲铁轨编号
	vector<stack<int>> tracks_buf(k);//缓冲铁轨数组

	int need = 1;//出轨处须要挂上的车厢号
	while (!datas.empty())
	{
		int d = datas.back();
		datas.pop_back();
		if (d==need)//符合要求直接移到出轨
		{
			results.push_front(need);
			need++;
			//再到缓冲铁轨中查找是否有下一个符合的车厢
			while(min_buf == need)//找到
			{
				results.push_front(need);
				need++;
				//移除缓冲铁轨
				tracks_buf[min_tra].pop();
				//更新min_buf、min_tra
				min_buf = n+2;
				min_tra = 0;
				updata(tracks_buf,min_buf,min_tra);
			}
		}
		else//不符合要求移到缓冲铁轨上
		{
			if(!trans(n,d,tracks_buf,min_buf,min_tra))
			{
				return false;
			}
		}
	}
		return true;
}
int main()
{
	int array[] = {5,8,1,7,4,2,9,6,3};
	deque<int> results;
	vector<int> vec(array,array+sizeof(array)/sizeof(array[0]));
	int n = vec.size();
	int k = 3;//3条缓冲铁轨

	if (fun(vec,results,n,k))
	{
		cout<<k<<"条缓冲铁轨能够将依照";
		copy(vec.begin(),vec.end(),ostream_iterator<int>(cout));
		cout<<"此序列的"<<n<<"节车厢又一次排好挂到火车头上。"<<endl;
		cout<<"排好后的序列是:"<<endl;
		copy(results.begin(),results.end(),ostream_iterator<int>(cout));
		cout<<endl;
	}
	else
	{
		cout<<"重排失败!"<<endl;
	}
}

posted @ 2017-08-15 19:37  mfmdaoyou  阅读(837)  评论(0编辑  收藏  举报