【问题描写叙述】

给定一个正整数N代表火车数量。0<N<10,接下来输入火车入站的序列,一共N辆火车,每辆火车以数字1-9编号。

要求以字典序排序输出火车出站的序列号。

输入:  

有多组測试用例,每一组第一行输入一个正整数N(0<N<10),第二行包含N个正整数,范围为1到9。

输出:  

输出以字典序排序的火车出站序列号,每一个编号以空格隔开,每一个输出序列换行。详细见sample。

例子输入: 

3

1 2 3

例子输出: 

1 2 3

1 3 2

2 1 3

2 3 1

3 2 1

【解题思路一】

栈具有先进后出、后进先出的特点,因此,不论什么一个调度结果应该是1 ,2 ,3 ,4全排列中的一个元素。因为进栈的顺序是由小到大的,所以出栈序列应该满足下面条件:对于序列中的不论什么一个数其后面全部比它小的数应该是倒序的,比如4321 是一个有效的出栈序列,1423不是一个有效的出栈结果(4 后面比它小的两个数 2 ,3 不是倒序)。

据此。本题能够通过算法产生n 个数的全排列,然后将满足出栈规则的序列输出。

依此递归定义。递归算法例如以下:

#include<stdio.h>
int cont=1;
void print(int str[],int n);
void perm(int str[],int k,int n)
{
int i,temp;
if(k==n-1)print(str,n);//k和n-1相等。即一趟递归走完
else{
for(i=k;i<n;i++){//把当前节点元素与兴许节点元素交换
temp=str[k]; str[k]=str[i]; str[i]=temp;//交换
perm(str,k+1,n);//把下一个节点元素与兴许节点元素交换
temp=str[i]; str[i]=str[k]; str[k]=temp;//恢复原状
}
}
}
/* 本函数推断整数序列 str[] 是否满足进出栈规则, 若满足则输出*/
void print(int str[],int n)
{
int i,j,k,l,m,flag=1,b[2];
for(i=0;i<n;i++) /* 对每一个str[i] 推断其后比它小的数是否为降序序列*/
{
m=0;
for(j=i+1;j<n&&flag;j++){
if (str[i]>str[j])
{
if (m==0) b[m++]=str[j];//记录str[i]后比它小的数
else
{
//假设之后出现的数比记录的数还大,改变标记变量
if (str[j]>b[0]) flag=0;
//否则记录这个更小的数
else b[0]=str[j];
}
}
}
}
if(flag) /* 满足出栈规则则输出 str[] 中的序列*/
{
printf(" %2d:",cont++); //输出序号
for(i=0;i<n;i++)
printf("%d",str[i]);//输出序列
printf("\n");
}
}
int main()
{
int str[100],n,i;
printf("input a int:"); /* 输出排列的元素个数*/
scanf("%d",&n);
for(i=0;i<n;i++) /* 初始化排列集合*/
str[i]=i+1; //第i个节点赋值为i+1
printf("input the result:\n");
perm(str,0,n); //调用递归
printf("\n");
return 0;
}

【解题思路二】                    

此处所谓字典序排序的意思是这n辆火车有多少种出站的可能顺序(也就是数据结构中的栈有多少种出栈顺序)。思路为用三个变量分别存储待进站火车,站中火车和已出站火车,当中待进站火车用Queue(队列)存储和站中火车採用stack(栈)存储,已出站火车採用StringBuilder来存储,详细实现是採用递归的方法,递归函数的參数为当前待进站火车、站中火车、已出站火车的值所组成的三元组,递归结束条件是。未进站火车和站中火车均为空。此时输出已出站火车即为全部出站的一种可能,递推关系为对于当前情况有让下一辆火车进站或让站中的一辆火车出站两种可能,对于两种可能分别调用递归函数。就可以得出问题的解。

【Java 实现】

【解题思路三】

该问题能够提炼成为给出进栈序列。求出全部的出栈顺序。该题是一道模拟题,模拟进栈出栈的顺序。对于每个元素进栈后 都能够有2种行为:出栈或者驻留在栈中。整个过程能够用一个树的形式来表达。因此採用回朔法(回溯法的过程就是一课树的形式)

//回溯法。其核心就是循环+递归。为了表示正确性,当中每一步操作(如改动数据,进栈等)
//都应该有对应的对称操作还原(如将改动数据还原,出栈等)
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std;
int num;
int input[10];
int output[10];
int output_index;
int heap[10];
int heap_index;
vector<int* >vec;
void DF(int n);
void df(int n)
{
if(heap_index==0)
return ;
//退出栈 放入输入队列中
output[output_index++]=heap[--heap_index]; //对称1
heap[heap_index]=0;
for(int i=0;i<2;i++)
{
if(i==0)
df(n);
else
DF(n+1);
}
heap[heap_index++]=output[--output_index]; //对称1
output[output_index]=0; } void DF(int n)
{
heap[heap_index++]=input[n]; //放入 。对称2
if(n==num-1) //该函数退出时(一般在回溯法中,在函数出口内部是不存在对称结构,可是该题中存在其它函数df调用该回溯函数,故返回到)
{
int temp=heap_index;
output[output_index++]=heap[--heap_index]; //对称3
heap[heap_index]=0; while(heap_index)
output[output_index++]=heap[--heap_index];
int *p=(int *)malloc(sizeof(int)*num);
for(int i=0;i<output_index;i++)
p[i]=output[i];
vec.push_back(p);
while(temp) //对称3
{
heap[heap_index++]=output[--output_index];
output[output_index]=0;
temp--;
}
heap[--heap_index]=0; //对称2
return ; }
for(int i=0;i<2;i++)
{
if(i==0)
df(n);
else
DF(n+1); //i==1的时候就是不将数据退出栈
}
heap[--heap_index]=0; //对称2 } bool cmp(int* t1,int* t2)
{
for(int i=0;i<num;i++)
{
if(t1[i]==t2[i])
continue;
return t1[i]<t2[i];
}
return true;
}
int main()
{
freopen("a.txt","r",stdin);
while(scanf("%d",&num)!=EOF)
{
memset(input,0,sizeof(input));
memset(output,0,sizeof(input));
memset(heap,0,sizeof(input));
output_index=0;
heap_index=0;
vec.clear();
for(int i=0;i<num;i++)
scanf("%d",input+i);
DF(0);
sort(vec.begin(),vec.end(),cmp);
for(unsigned int i=0;i<vec.size();i++)
{
for(int j=0;j<num-1;j++)
printf("%d ",vec[i][j]);
printf("%d\n",vec[i][num-1]);
}
}
return 0;
}

【解题思路四】

STL方法:1、若n=1那么就一种排列方式。2、n>1时先求出n-1的出栈顺序。再分开将n插入n-1之前。n-1之后和每个n-1之后的每个数!

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std; void helper(string &inTrain,vector<string> &outTrain,int index){
if(index == inTrain.size()){
return;
}//if
if(index == 0){
string outNum("");
outNum += inTrain[index];
outTrain.push_back(outNum);
}//if
else{
vector<string> newOutTrain;
// 出栈序列
int size = outTrain.size();
// 第index辆火车进栈
for(int i = 0;i < size;++i){
// 第i个出栈序列
int count = outTrain[i].size();
// 寻找前一个进栈的火车下标
int targetIndex;
for(int j = 0;j < count;++j){
if(inTrain[index-1] == outTrain[i][j]){
targetIndex = j;
break;
}//if
}//for
string tmp(outTrain[i]);
for(int j = targetIndex;j <= count;++j){
tmp.insert(tmp.begin()+j,inTrain[index]);
newOutTrain.push_back(tmp);
tmp.erase(tmp.begin()+j);
}//for
}//for
swap(outTrain,newOutTrain);
}//else
helper(inTrain,outTrain,index+1);
} vector<string> TrainLeft(string inTrain){
vector<string> result;
int size = inTrain.size();
if(size <= 0){
result;
}//if
helper(inTrain,result,0);
sort(result.begin(),result.end());
return result;
} int main(){
int n;
//freopen("C:\\Users\\Administrator\\Desktop\\c++.txt","r",stdin);
while(cin>>n){
string train("");
int num;
for(int i = 1;i <= n;++i){
cin>>num;
train += num + '0';
}//for
vector<string> trainNum = TrainLeft(train);
// 输出
int size = trainNum.size();
for(int i = 0;i < size;++i){
int count = trainNum[i].size();
for(int j = 0;j < count;++j){
if(j == 0){
cout<<trainNum[i][j];
}//if
else{
cout<<" "<<trainNum[i][j];
}//else
}//for
cout<<endl;
}//for
}//while
return 0;
}

C++ HOJ 火车进站的更多相关文章

  1. 华为OJ:火车进站

    火车进站 给定一个正整数N代表火车数量,0<N<10,接下来输入火车入站的序列,一共N辆火车,每辆火车以数字1-9编号.要求以字典序排序输出火车出站的序列号. 输入描述: 有多组测试用例, ...

  2. (hdu)1022 Train Problem I 火车进站问题

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1022 Problem Description As the new term comes, ...

  3. CodeVS3958 火车进站

    3958 火车进站 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 大师 Master         题目描述 Description 火车站内往往设有一些主干线分叉出去的铁路支路 ...

  4. HDU 1022 火车进站【栈】

     题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1022 题目大意: 题目大概意思:有N辆火车,以序列1方式进站,判断是否能以序列2方式出栈.进站不一定 ...

  5. 华为OJ—火车进站(栈,字典排序)

    http://career-oj.huawei.com/exam/ShowSolution?method=SolutionApp&id=2282 给定一个正整数N代表火车数量,0<N&l ...

  6. poj 1363 火车进站 (栈的应用)

    Description There is a famous railway station in PopPush City. Country there is incredibly hilly. Th ...

  7. 火车进站输出路径(HDU1022)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1022 解题报告: 思路: 就是维护好这个栈,只要它不是空,并且头部和ans相同,就一直出栈,直到不满足 ...

  8. 火车安排问题(dp好题)

    火车站内往往设有一些主干线分叉出去的铁路支路,供火车停靠,以便上下客或装载货物.铁路 支路有一定长度:火车也有一定的长度,且每列火车的长度相等. 假设某东西向的铁路上,有一小站.该站只有一条铁路支路可 ...

  9. HDU 1022(火车过站 栈)

    题意是给定火车进站的序列和出站的序列,问能否完成转换,若能输出过程. 和另一道以火车进站为背景的栈应用题类似,但增加了对于过程的输出,只需要多记录一下进出站顺序即可. #include <bit ...

随机推荐

  1. 被忽视的控件UIToolbar

    前言 UIToolbar以前也接触过,不过没有怎么用,久而久之就忘了他的存在,今天看别人源码的时候看见了,它怎么很方便,在排列一排视图的时候不需要我们算里面的坐标就可以轻松良好的把布局做出来 代码 U ...

  2. ios sqlite 简单使用

    // // ViewController.m // sqlitedemo // // Created by lam_TT on 15-4-11. // Copyright (c) 2015年 lam_ ...

  3. POJ——3159Candies(差分约束SPFA+前向星+各种优化)

    Candies Time Limit: 1500MS   Memory Limit: 131072K Total Submissions: 28071   Accepted: 7751 Descrip ...

  4. [luoguP3960] 列队(动态开点线段树)

    传送门 有splay的做法,有树状数组的做法... 最好理解的还是线段树的做法. 一开始我是这样想的,如果移动某一个人,只有当前行和最后一列会受到影响,感觉就像是个线段树,树状数组什么的. 然而接下来 ...

  5. 【DFS求树的最大二分匹配+输入外挂】HDU 6178 Monkeys

    http://acm.hdu.edu.cn/showproblem.php?pid=6178 [题意] 给定一棵有n个结点的树,现在有k个猴子分布在k个结点上,我们可以删去树上的一些边,使得k个猴子每 ...

  6. 【极角排序+双指针线性扫】2017多校训练七 HDU 6127 Hard challenge

    acm.hdu.edu.cn/showproblem.php?pid=6127 [题意] 给定平面直角坐标系中的n个点,这n个点每个点都有一个点权 这n个点两两可以连乘一条线段,定义每条线段的权值为线 ...

  7. 【bzoj1299】[LLH邀请赛]巧克力棒 博弈+模拟

    Description TBL和X用巧克力棒玩游戏.每次一人可以从盒子里取出若干条巧克力棒,或是将一根取出的巧克力棒吃掉正整数长度.TBL先手两人轮流,无法操作的人输. 他们以最佳策略一共进行了10轮 ...

  8. NAND FLASH 物理结构分析

    转自:http://blog.51cto.com/hardywang/2053915 NAND Flash是一种非易失性随机访问存储介质,基于浮栅(Floating Gate)晶体管设计,通过浮栅来锁 ...

  9. Python入门--10--序列

    一.与列表.元祖的相同与不同 1.都可以通索引得到元素 2.默认索引从0开始 3.可以通过分片得到一个范围内的元素集合 4.有很多共同的操作符 二. 1.list()这个函数用法 a="we ...

  10. ShareSDK中微信分享错误总结

    项目中用到微信分享,可向好友或朋友圈分享链接时,分享人可以打开网站,查看消息者却始终不能打开网站.试了N种方法,重写了N次分享模块,均没办法解决. 在无意中查看分享链接时发现,朋友圈里分享后,原始链接 ...