6-19 骑士征途问题
问题描述
在一个 n*n 个方格的国际象棋棋盘上,马(骑士)从任意指定方格出发,按照横 1 步竖2 步,或横 2 步竖 1 步的跳马规则,走遍棋盘的每一个格子,且每个格子只走 1 次。这样的 跳马步骤称为 1 个成功的骑士征途。例如,当 n=5 时的 1 个成功的骑士征途如下图所示。
对于给定的 n 和 n*n 方格的起始位置 x 和 y。用分支限界法找出从指定的方格(x,y)出发 的一条成功的骑士征途。
数据输入:
第一行有 1 个正整数 n (1≤n≤10);第二行有 2 个正整 数 x 和 y,表示骑士的起始位置为(x,y)。
Java
package Chapter6FenZhiXianJieFa;
import java.util.*;
public class QiShiZhengTu {
private static class Point implements Comparable{
int x;
int y;
int step;
int[][] board;
public int compareTo(Object o){
Point point = (Point) o;
int result = Integer.compare(point.step, step);
return result;
}
}
private static int[] dx = {-2, -1, 1, 2, -2, -1, 2, 1};
private static int[] dy = {-1, -2, -2, -1, 1, 2, 1, 2};
private static int n;
private static int[][] board;
private static int startX,startY;
private static Point E,N;
private static Queue<Point> Q;
public static void main(String[] args){
int step = 1;
Scanner input = new Scanner(System.in);
while (true){
n = input.nextInt();
startX = input.nextInt();
startY = input.nextInt();
board = new int[n+1][n+1];
board[startX][startY] = 1;
fifobb(step);
}
}
private static void fifobb(int step){
Q = new PriorityQueue<>();
E = new Point();
E.step = step;
E.x = startX;
E.y = startY;
E.board = new int[n+1][n+1];
arrayCopy(board, E.board);
//搜索排列空间树
while (true){
if(answer()) {record(); break;}
else
for(int i=0; i<8; i++){
newNode(i);
if(constrain() && bound()) enQueue();
}
if(!getNext()) break;
}
output();
}
private static void record(){
arrayCopy(E.board, board);
}
public static void arrayCopy(int[][] src, int[][] des){
for(int i=0; i<src.length; i++)
des[i] = Arrays.copyOf(src[i], src[i].length);
}
private static boolean getNext(){
if(Q.isEmpty()) return false;
E = Q.poll();
E.board[E.x][E.y] = E.step;
return true;
}
private static void enQueue(){
N.step++;
Q.add(N);
}
private static boolean bound(){
return true;
}
private static boolean constrain(){
if (N.x < 1 || N.y < 1 || N.x > n || N.y > n || N.board[N.x][N.y] != 0)
return false;
else
return true;
}
private static void newNode(int i){
N = new Point();
N.x = E.x+dx[i];
N.y = E.y+dy[i];
N.step = E.step;
N.board = new int[n+1][n+1];
arrayCopy(E.board, N.board);
}
private static boolean answer(){
return E.step==n*n;
}
private static void output(){
if(E.step < n*n){
System.out.println("No solution!");
}else {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++)
System.out.print(String.format("%4d", board[i][j]));
System.out.println();
}
}
}
}
Input & Output
5
1 3
19 10 1 16 25
2 15 18 11 6
9 20 5 24 17
14 3 22 7 12
21 8 13 4 23
Reference
王晓东《计算机算法设计与分析》