算法设计与分析: 5-26 多轨车皮编序问题

5-26 多轨车皮编序问题


问题描述

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

多轨车皮编序

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

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


Java

package Chapter5HuiSuFa;

import java.util.Scanner;

public class DuoGuiChePiBianXu {

    private static class Move{
        int code;
        int source;
        int target;
    }

    private static int MAX = 10000;
    private static int MAXSHORT = 10000;
    private static int n,k;
    private static int[] top;
    private static int[][] sta;
    private static int best;

    private static int scount,gcount;

    private static Move[] solu,opt;

    public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        while (true){
            best = MAX;

            n = input.nextInt();
            k = input.nextInt();

            top = new int[k+2];
            sta = new int[k+2][n+1];
            solu = new Move[MAX];
            opt = new Move[MAX];

            for(int i=0; i<=k; i++){
                top[i] = input.nextInt();
                for(int j=1; j<=top[i]; j++)
                    sta[i][j] = input.nextInt();
            }
            for(int i=1; i<n+1; i++)
                sta[k+1][i] = i;
            top[k+1] = 0;
            sta[k][0] = n+1;
            backtrack(0);
            if(best == MAXSHORT)
                System.out.println("No Solution!");
            else {
                System.out.println(best);
                output(opt,best);
            }
        }
    }

    private static boolean moves(){
        boolean t = true;
        while (t){
            t = false;
            if(top[k+1] == n){
                if(best > gcount){
                    best = gcount;
                    copyans(gcount);
                }
                scount++;
                return true;
            }
            for(int i=0; i<=k; i++)
                if(top[i]>0 && sta[i][top[i]]==sta[k+1][top[k+1]+1]){
                    move(i,k+1,++gcount);
                    t = true;
                }
        }

        return false;
    }

    private static void move(int i, int j, int count){
        solu[count] = new Move();
        solu[count].code = sta[i][top[i]];
        solu[count].source = i;
        solu[count].target = j;
        sta[j][top[j]+1] = sta[i][top[i]];
        top[j]++; top[i]--;
    }

    private static void copyans(int k){
        for(int i=1; i<=k; i++){
            opt[i] = new Move();
            opt[i].code = solu[i].code;
            opt[i].source = solu[i].source;
            opt[i].target = solu[i].target;
        }
    }

    private static void backtrack(int count){
        int[] stop = new int[k+2];
        int[][] ssta = new int[k+2][n+1];
        int count1;
        gcount = count;
        if(moves()) return;
        save(ssta,stop);
        count1 = gcount+1;
        for(int i=0; i<k; i++)
            for(int j=i+1; j<=k; j++)
                if(top[i]>0 && (j<k || j==k&&sta[i][top[i]]<sta[j][top[j]])){
                    move(i,j,count1);
                    backtrack(count1);
                    restore(ssta,stop);
                }
    }

    private static void save(int[][] a, int[] b){
        for(int i=0; i<k+2; i++){
            b[i] = top[i];
            for(int j=0; j<=n; j++)
                a[i][j] = sta[i][j];
        }
    }

    private static void restore(int[][] a, int[] b){
        for(int i=0; i<k+2; i++){
            top[i] = b[i];
            for(int j=0; j<=n; j++)
                sta[i][j] = a[i][j];
        }
    }

    private static void output(Move[] opt, int best){
        for(int i=1; i<=best; i++)
            System.out.println(opt[i].code+" "+opt[i].source+" "+opt[i].target);
    }
}

Input & Output

6 2
4 4 1 5 3 
2 6 2 
0
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



11 3
2 4 7 
9 9 10 2 3 1 5 8 11 6 
0 
0 
18
7 0 2
6 1 2
11 1 3
8 1 3
5 1 2
1 1 4
3 1 2
2 1 4
3 2 4
4 0 4
5 2 4
6 2 4
7 2 4
8 3 4
10 1 2
9 1 4
10 2 4
11 3 4

Reference

王晓东《计算机算法设计与分析》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值