算法设计与分析: 6-24 最长距离问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/IOIO_/article/details/81208633

6-24 最长距离问题


问题描述

重排九宫是一个古老的单人智力游戏。据说重排九宫起源于我国古时由三国演义故事“关羽义释曹操”而设计的智力玩具“华容道”,后来流传到欧洲,将人物变成数字。原始 的重排九宫问题是这样的:将数字 1~8 按照任意次序排在 3 × 3 的方格阵列中,留下一个空 格。与空格相邻的数字,允许从上,下,左,右方向移动到空格中。游戏的最终目标是通过 合法移动,将数字 1~8 按行排好序。最长距离问题考察的是,从数字 1~8 在 3 × 3 的方格阵 列的初始排列 A 出发,找出与其相应的最长距离目标状态 B。换句话说,从 A 到 B 的最优移动序列的长度最长。

最长距离问题

对于给定的 3 × 3 方格阵列中数字 1~8 初始排列,编程计算与初始排列相应的最长距离目标状态。

数据输入:
有 3 行,每行有 3 个数字表示该行方格中的数字, 0 表示空格。


Java

package Chapter6FenZhiXianJieFa;

import java.util.Scanner;

public class ZuiChangJuLi {

    private static class Node{
        int code,dep,dir,parent;
    }

    private static final char[] op = {'U','D','L','R'};

    private static final int Bitsint = 32;
    private static final int Rowsz = 3;
    private static final int Permsz = Rowsz*Rowsz;

    private static Node[] buff;
    private static int first,last,fact,masksz;
    private static int[] bitset;
    private static int[] sour = new int[Permsz];
    private static int[] perm = new int[Permsz];

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

        while (true){
            init(input);

            fifobb();

            output();
        }
    }

    private static void init(Scanner input){
        fact = 1;
        for(int i=0,n=0; i<Permsz; i++){
            n = input.nextInt();
            if(n == 0) sour[i]=Permsz-1;
            else sour[i]=n-1;
            fact *= i+1;
            perm[i] = sour[i];
        }
        int icode = ptoi(sour);
        masksz = (fact+Bitsint-1)/Bitsint;
        bitset = new int[masksz];
        for(int i=0; i<masksz; i++) bitset[i]=0;
        bitset[icode/Bitsint] |= 1<<(icode%Bitsint);
        first=0; last=0;
        buff = new Node[fact/2];
        for(int i=0; i<fact/2; i++)
            buff[i] = new Node();
        buff[last].parent = -1;
        buff[last].dep = 0;
        buff[last++].code = icode;
    }

    private static int ptoi(int[] perm){
        int[] pcpy = new int[Permsz];
        int[] invp = new int[Permsz];
        int n = 0;
        for(int i=0; i<Permsz; i++){
            pcpy[i] = perm[i];
            invp[perm[i]] = i;
        }
        for(int i=Permsz-1; i>0; i--){
            int p = invp[i];
            pcpy[p] = pcpy[i];
            pcpy[i] = i;
            invp[pcpy[p]] = p;
            invp[i] = i;
            n *= i+1;
            n += i-p;
        }

        return n;
    }

    private static void itop(int[] perm, int n){
        perm[0] = 0;
        for(int i=1; i<Permsz; i++){
            int p = i-n%(i+1);
            perm[i] = perm[p];
            perm[p] = i;
            n /= i+1;
        }
    }

    private static void fifobb(){
        while (first < fact/2){
            int code = buff[first].code;
            itop(perm,code);
            int i;
            for(i=0; perm[i]!=Permsz-1 && i<Permsz; i++);
            int brow = i/Rowsz;
            int bcol = i%Rowsz;
            for(int d=0; d<4; d++) trymove(brow,bcol,i,d);
            first++;
        }
    }

    private static void trymove(int brow, int bcol, int i, int d){
        switch (d){
            case 0:
                if(brow > 0){
                    swap(perm,i,i-Rowsz);
                    addperm(d);
                    swap(perm,i,i-Rowsz);
                }
                break;

            case 1:
                if(brow < Rowsz-1){
                    swap(perm,i,i+Rowsz);
                    addperm(d);
                    swap(perm,i,i+Rowsz);
                }
                break;

            case 2:
                if(bcol > 0){
                    swap(perm,i,i-1);
                    addperm(d);
                    swap(perm,i,i-1);
                }
                break;

            case 3:
                if(bcol < Rowsz-1){
                    swap(perm,i,i+1);
                    addperm(d);
                    swap(perm,i,i+1);
                }
        }
    }

    private static void swap(int[] perm, int i, int j){
        int tmp = perm[i];
        perm[i] = perm[j];
        perm[j] = tmp;
    }

    private static void addperm(int dir){
        int code = ptoi(perm);
        int m = code/Bitsint;
        int n = code%Bitsint;
        if(((bitset[m]>>n)&1) > 0) return;
        bitset[m] |= 1<<n;
        buff[last].parent = first;
        buff[last].dir = dir;
        buff[last].dep = buff[first].dep+1;
        buff[last++].code = code;
    }

    private static void output(){
        int best = 0;
        int i;
        int j = 0;
        for(i=0; i<fact/2; i++)
            if(buff[i].dep >= best){
                best = buff[i].dep;
                j = i;
            }
        for(i=0,j=0; i<fact/2; i++)
            if(buff[i].dep == best)
                j++;

        System.out.println(best+" "+j);

        for(i=0,j=0; i<fact/2; i++)
            if(buff[i].dep == best){
                itop(perm,buff[i].code);
                outperm();
                outmove(i);
                System.out.println();
            }
    }

    private static void outmove(int first){
        if(buff[first].dep == 0) return;
        outmove(buff[first].parent);

        System.out.print(op[buff[first].dir]);
    }

    private static void outperm(){
        for(int i=0; i<Permsz; i++){
            System.out.print((perm[i]+1)%Permsz+" ");
            if((i+1)%Rowsz == 0)
                System.out.println();
        }
    }
}

Input & Output

2 6 4
1 3 7
0 5 8
31 2
8 7 1 
0 3 5 
4 6 2 
UURDDLUURRDDLURDLLUURDLURRDDLLU
8 1 5 
7 3 6 
4 0 2 
UURDDRULLURRDLLDRRULULDDRUULDDR


7 0 3 
8 1 2 
6 5 4 
31 2
4 6 0 
2 1 5 
3 8 7 
DDLUURRDDLULURRDDLULURRDDLLUURR
0 4 6 
5 1 8 
3 2 7 
DDLURRULLDRRDLLURURDDLUURDDLLUU



0 8 6
5 4 7
2 3 1
31 2
1 3 2 
0 4 8 
6 7 5 
DDRUULDDRRUULDRULLDDRULDRRUULLD
1 0 2 
7 4 3 
6 5 8 
DDRUURDLLDRRULLURRDLDLUURDDLUUR

Reference

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

猜你喜欢

转载自blog.csdn.net/IOIO_/article/details/81208633