zoukankan      html  css  js  c++  java
  • 多轨车皮编序问题

    Description

    在一个列车调度站中,k条轨道连接到k条侧轨处,形成k个铁路转轨栈,从左到右依次编号为1,2,…,k。其中左边轨道为车皮入口,编号为0;右边轨道为出口,编号为k+1。当k=2 时,如下图所示。编号为1,2,…,n的n个车皮散乱地停放在编号为0,1,2,…,k的栈轨处。调度室要安排各车皮进出栈次序,使得在出口处各车皮按照其编号次序1,2,…,n依次出站。车皮移动时只能按照从左到右的方向移动。

    编程任务:给定车皮数n和侧轨数k,以及各车皮的位置,编程计算最优调度方案,使得移动车皮的总次数最少。

    Input

    第一行有2 个正整数n和k,表示车皮数为n和侧轨数为k。接下来的k+1行中,表示编号为0,1,2,…,k 的栈轨处按照从下到上的顺序停放的车皮序列。每行的第一个数表示该栈轨处的车皮数,紧接着是车皮序列。

    Output

    文件的第一行是最少移动次数m。接下来的m行是对应于最优方案的m次移动。每次移动用形如‘c x y’的3个整数来表示,其中c 表示车皮编号,x 表示起始栈轨号,y 表示目标栈轨号。如果无法调度则输出“No Solution!”。

    Sample Input

    6 2
    4 4 1 5 3
    2 6 2
    0
    

    Sample Output

    9
    3 0 1
    5 0 2
    1 0 3
    3 1 2
    2 1 3
    3 2 3
    4 0 3
    5 2 3
    6 1 3
    

    题解

    定义

    (top[])记录每一个栈的元素个数,(mp[][])记录每一个栈的各个元素,(Ansn)(Ans[])记录答案个数已及答案,(Res[])记录过程。

    const int N=120,INF=999999;
    int n,k,top[N],mp[N][N],Ansn;
    struct node
    {
    	int c,x,y;
    }Ans[N*N],Res[N*N];
    

    读入

    void Read()
    {
    	scanf("%d%d",&n,&k);
    	for(int i=0;i<=k;++i)
    	{
    		scanf("%d",&top[i]);
    		for(int j=1;j<=top[i];++j) scanf("%d",&mp[i][j]);
    	}
    	top[k+1]=0;
    	for(int i=1;i<=n;++i) mp[k+1][i]=i;
    }
    

    回溯

    回溯用了两个数组来记录上一步的状态。

    void Copy(int (*tmpmp)[N],int mp[N][N],int *tmptop,int top[N])
    {
    	for(int i=0;i<=k+1;++i)
    		for(int j=0;j<=n;++j) tmpmp[i][j]=mp[i][j];
    	for(int i=0;i<=k+1;++i) tmptop[i]=top[i];
    }
    

    移动

    (Move(x,y,t))表示将(x)栈的顶部元素移至(y)栈,并且是第(t)步的操作。

    void Move(int x,int y,int t)
    {
    	Res[t]=(node){mp[x][top[x]],x,y},
    	mp[y][top[y]+1]=mp[x][top[x]],
    	--top[x],++top[y];
    }
    

    进入第(k+1)个栈

    (Check)函数返回值为(1)时,表示所有的都移动完成,即所有的数都进入了第(k+1)个栈。

    bool Check(int &t)
    {
    	bool flag=1;
    	while(flag)
    	{
    		flag=0;
    		if(top[k+1]>=n)
    		{
    			if(t<Ansn)
    			{
    				Ansn=t;
    				for(int i=1;i<=Ansn;++i) Ans[i]=Res[i];
    			}
    			return 1;
    		}
    		for(int i=0;i<=k;++i)
    			if(top[i]&&mp[i][top[i]]==mp[k+1][top[k+1]+1])
    			{
    				Move(i,k+1,++t); flag=1;
    			}
    	}
    	return 0;
    }
    

    (DFS)

    这个只能靠自己去领悟……

    void Dfs(int t)
    {
    	if(t>=Ansn) return;
    	if(Check(t)) return;
    	++t;
    	int tmpmp[N][N],tmptop[N];
    	Copy(tmpmp,mp,tmptop,top);
    	for(int i=0;i<k;++i)
    		for(int j=i+1;j<=k;++j)
    			if(top[i]&&((!top[j])||(mp[i][top[i]]<mp[j][top[j]])))
    			{
    				Move(i,j,t);
    				Dfs(t),
    				Copy(mp,tmpmp,top,tmptop);
    			}
    }
    

    输出

    void Print()
    {
    	if(Ansn==INF)
    	{
    		puts("No Solution!");
    		return;
    	}
    	printf("%d
    ",Ansn);
    	for(int i=1;i<=Ansn;++i) printf("%d %d %d
    ",Ans[i].c,Ans[i].x,Ans[i].y);
    }
    

    整体代码

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    const int N=120,INF=999999;
    int n,k,top[N],mp[N][N],Ansn;
    struct node
    {
    	int c,x,y;
    }Ans[N*N],Res[N*N];
    
    void Read()
    {
    	scanf("%d%d",&n,&k);
    	for(int i=0;i<=k;++i)
    	{
    		scanf("%d",&top[i]);
    		for(int j=1;j<=top[i];++j) scanf("%d",&mp[i][j]);
    	}
    	top[k+1]=0;
    	for(int i=1;i<=n;++i) mp[k+1][i]=i;
    }
    
    void Move(int x,int y,int t)
    {
    	Res[t]=(node){mp[x][top[x]],x,y},
    	mp[y][top[y]+1]=mp[x][top[x]],
    	--top[x],++top[y];
    }
    
    bool Check(int &t)
    {
    	bool flag=1;
    	while(flag)
    	{
    		flag=0;
    		if(top[k+1]>=n)
    		{
    			if(t<Ansn)
    			{
    				Ansn=t;
    				for(int i=1;i<=Ansn;++i) Ans[i]=Res[i];
    			}
    			return 1;
    		}
    		for(int i=0;i<=k;++i)
    			if(top[i]&&mp[i][top[i]]==mp[k+1][top[k+1]+1])
    			{
    				Move(i,k+1,++t); flag=1;
    			}
    	}
    	return 0;
    }
    
    void Copy(int (*tmpmp)[N],int mp[N][N],int *tmptop,int top[N])
    {
    	for(int i=0;i<=k+1;++i)
    		for(int j=0;j<=n;++j) tmpmp[i][j]=mp[i][j];
    	for(int i=0;i<=k+1;++i) tmptop[i]=top[i];
    }
    
    void Dfs(int t)
    {
    	if(t>=Ansn) return;
    	if(Check(t)) return;
    	++t;
    	int tmpmp[N][N],tmptop[N];
    	Copy(tmpmp,mp,tmptop,top);
    	for(int i=0;i<k;++i)
    		for(int j=i+1;j<=k;++j)
    			if(top[i]&&((!top[j])||(mp[i][top[i]]<mp[j][top[j]])))
    			{
    				Move(i,j,t);
    				Dfs(t),
    				Copy(mp,tmpmp,top,tmptop);
    			}
    }
    
    void Print()
    {
    	if(Ansn==INF)
    	{
    		puts("No Solution!");
    		return;
    	}
    	printf("%d
    ",Ansn);
    	for(int i=1;i<=Ansn;++i) printf("%d %d %d
    ",Ans[i].c,Ans[i].x,Ans[i].y);
    }
    
    int main()
    {
    	Read(); Ansn=INF;
    	Dfs(0),Print();
    	return 0;
    }
    

    本文作者:OItby @ https://www.cnblogs.com/hihocoder/

    未经允许,请勿转载。

  • 相关阅读:
    svg使用
    人生是 立体, 不是平面, 股票大作手不太好的结局
    react 管理平台
    首页性能优化
    vue 安装插件
    python中如何对list之间求交集,并集和差集
    Java中String直接复制和new String创建对象的区别以及equals和==的区别和效率对比
    关于二叉树的总结
    Postgresql 数据库,如何进行数据备份以及导入到另外的数据库
    Java List详解,面试中应该如何解答关于List的问题
  • 原文地址:https://www.cnblogs.com/hihocoder/p/11409052.html
Copyright © 2011-2022 走看看