2-4 马的Hamilton周游路线问题
问题描述
8*8的国际象棋棋盘上的一只马,恰好走过除起点外的其他63个位置各一次,最后回到起点,这条路线称为马的一条Hamilton周游路线。对于给定的m*n的国际象棋棋盘,m和n均为大于5的偶数,且|m-n|≤2,试设计一个分治算法找出马的一条Hamilton周游路线。
回溯法
Java
public class Main {
private static int max = 101;
private static int[][] board = new int[max][max];
private static int startX, startY;
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 m = 8;//行
private static int n = 6;//列
public static void main(String[] args) {
startX = 2;
startY = 2;
int number = 1;
board[startX][startY] = 1;
backtrack(startX, startY, number);
}
private static void backtrack(int x, int y, int num) {
//已经走完棋盘中所有的点
if (num == n * m && isNextStepStartPoint(x, y)) {
print(n, m);
System.exit(1);
}
//表示每一个格都有八种走法
for (int i = 0; i < 8; i++) {
int nextX = x + dx[i];
int nextY = y + dy[i];
if (isNextStepOk(nextX, nextY)) {
//走到下一个位置,设置其序号为 number+1
board[nextX][nextY] = num + 1;
backtrack(nextX, nextY, num + 1);
//回溯
board[nextX][nextY] = 0;
}
}
}
//判断下一步是否回到起点
private static boolean isNextStepStartPoint(int x, int y) {
for (int i = 0; i < 8; i++) {
if (x + dx[i] == startX && y + dy[i] == startY)
return true;
}
return false;
}
private static void print(int n, int m) {
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++)
System.out.print(String.format("%4d", board[i][j]));
System.out.println();
}
if(board[1][1] != 1){
System.out.println("-------Change to start from (1,1)--------");
int tmpStart = board[1][1];
for(int i=1; i<=m; i++)
for(int j=1; j<=n; j++)
if(board[i][j] > tmpStart)
board[i][j] = board[i][j]-tmpStart+1;
else if(board[i][j] < tmpStart)
board[i][j] = board[i][j]+m*n-tmpStart+1;
else
board[i][j] = 1;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++)
System.out.print(String.format("%4d", board[i][j]));
System.out.println();
}
}
//参数x,y 表示棋盘的位置
//检测(x,y) 对应位置在棋盘中是否合法
private static boolean isNextStepOk(int x, int y) {
if (x < 1 || y < 1 || x > m || y > n || board[x][y] != 0)
return false;
else
return true;
}
}
Output
7 4 19 48 21 44
18 1 6 45 34 47
5 8 3 20 43 22
2 17 10 33 46 35
9 14 27 36 23 42
28 11 16 39 32 37
15 26 13 30 41 24
12 29 40 25 38 31
-------Change to start from (1,1)--------
1 46 13 42 15 38
12 43 48 39 28 41
47 2 45 14 37 16
44 11 4 27 40 29
3 8 21 30 17 36
22 5 10 33 26 31
9 20 7 24 35 18
6 23 34 19 32 25
队列
Java
import java.util.LinkedList;
import java.util.Queue;
class Point{
int x;
int y;
}
public class Main {
private static int max = 101;
private static int[][] board = new int[max][max];//下标从1开始
private static int startX, startY;
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 m = 8;//行
private static int n = 6;//列
public static void main(String[] args) {
startX = 2;
startY = 2;
int number = 1;
board[startX][startY] = 1;
backtrack(startX, startY, number);
}
private static void backtrack(int x, int y, int num) {
//已经走完棋盘中所有的点
if (num == n * m && isNextStepStartPoint(x, y)) {
print(n, m);
System.exit(1);
}else {
Queue<Point> pointQueue = new LinkedList<>();
int minStep = 8;
for(int i=0; i<8; i++){
int pointX = x + dx[i];
int pointY = y + dy[i];
if(isNextStepOk(pointX, pointY)){
Point t = new Point();
t.x = pointX;
t.y = pointY;
int tmpStep = nextPossibleSteps(pointX, pointY);
if(tmpStep <= minStep)
{
minStep = tmpStep;
// ((LinkedList<Point>) pointQueue).add(0, t);
((LinkedList<Point>) pointQueue).addFirst(t);
}else
pointQueue.add(t);
}
}
while(!pointQueue.isEmpty()){
Point point = pointQueue.poll();
board[point.x][point.y] = num+1;
backtrack(point.x, point.y, num+1);
board[point.x][point.y] = 0;
}
}
}
//判断下一步是否回到起点
private static boolean isNextStepStartPoint(int x, int y) {
for (int i = 0; i < 8; i++) {
if (x + dx[i] == startX && y + dy[i] == startY)
return true;
}
return false;
}
private static void print(int n, int m) {
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++)
System.out.print(String.format("%4d", board[i][j]));
System.out.println();
}
if(board[1][1] != 1){
System.out.println("-------Change to start from (1,1)--------");
int tmpStart = board[1][1];
for(int i=1; i<=m; i++)
for(int j=1; j<=n; j++)
if(board[i][j] > tmpStart)
board[i][j] = board[i][j]-tmpStart+1;
else if(board[i][j] < tmpStart)
board[i][j] = board[i][j]+m*n-tmpStart+1;
else
board[i][j] = 1;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++)
System.out.print(String.format("%4d", board[i][j]));
System.out.println();
}
}
//参数x,y 表示棋盘的位置
//检测(x,y) 对应位置在棋盘中是否合法
private static boolean isNextStepOk(int x, int y) {
if (x < 1 || y < 1 || x > m || y > n || board[x][y] != 0)
return false;
else
return true;
}
//该处有效的下一步有多少种
private static int nextPossibleSteps(int x, int y){
int steps = 0;
for(int i=0; i<8; i++){
if(isNextStepOk(x+dx[i], y+dy[i]))
steps++;
}
return steps;
}
}
Output
37 22 13 2 35 24
12 1 36 23 14 3
21 38 11 48 25 34
10 45 32 39 4 15
31 20 47 16 33 26
46 9 44 27 40 5
19 30 7 42 17 28
8 43 18 29 6 41
-------Change to start from (1,1)--------
1 34 25 14 47 36
24 13 48 35 26 15
33 2 23 12 37 46
22 9 44 3 16 27
43 32 11 28 45 38
10 21 8 39 4 17
31 42 19 6 29 40
20 7 30 41 18 5
优先队列
Java
import java.util.Comparator;
import java.util.PriorityQueue;
class Point{
int x;
int y;
int nextPossibleSteps;//表示当前点的下一位置有多少种走法;走法少的优先考虑
int currentToMidLength;//表示当前点与中心点的距离;距离中心点远的优先考虑
}
//class Point implements Comparable {
// int x;
// int y;
// int nextPossibleSteps;//表示当前点的下一位置有多少种走法;走法少的优先考虑
// int currentToMidLength;//表示当前点与中心点的距离;距离中心点远的优先考虑
//
// public int compareTo(Object o) {
// Point point=(Point) o;
// int result = Integer.compare(nextPossibleSteps, point.nextPossibleSteps);//先按 下次可能步数 由小到大 排列
// if(result == 0){
// result = Integer.compare(point.currentToMidLength, currentToMidLength);//下次可能步数 相同时,再按 与中心点距离 由大到小 排列
// }
// return result;
// }
//
//}
public class Main {
private static int max = 101;
private static int[][] board = new int[max][max];
private static int startX, startY;
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 m = 12;//行
private static int n = 10;//列
public static void main(String[] args) {
//从中心位置开始,程序运行容易得到结果
startX = 5;
startY = 5;
int number = 1;
board[startX][startY] = 1;
backtrack(startX, startY, number);
}
private static void backtrack(int x, int y, int num) {
//已经走完棋盘中所有的点
if (num == n * m && isNextStepStartPoint(x, y)) {
print(n, m);
System.exit(1);
}else {
PriorityQueue<Point> pointPriorityQueue = new PriorityQueue<>(8, pointComparator);
// PriorityQueue<Point> pointPriorityQueue = new PriorityQueue<>(8);
for(int i=0; i<8; i++){
int pointX = x + dx[i];
int pointY = y + dy[i];
if(isNextStepOk(pointX, pointY)){
Point t = new Point();
t.x = pointX;
t.y = pointY;
t.nextPossibleSteps = nextPossibleSteps(pointX, pointY);
t.currentToMidLength = currentToMidLength(pointX, pointY);
pointPriorityQueue.add(t);
}
}
while(!pointPriorityQueue.isEmpty()){
Point point = pointPriorityQueue.poll();
board[point.x][point.y] = num+1;
backtrack(point.x, point.y, num+1);
board[point.x][point.y] = 0;
}
}
}
private static Comparator<Point> pointComparator = new Comparator<Point>() {
@Override
public int compare(Point c1, Point c2) {
int result = Integer.compare(c1.nextPossibleSteps, c2.nextPossibleSteps);//先按 下次可能步数 由小到大 排列
// int result = result = Integer.compare(c2.nextPosToMidLength, c1.nextPosToMidLength);
if(result == 0){
result = Integer.compare(c2.currentToMidLength, c1.currentToMidLength);//下次可能步数 相同时,再按 与中心点距离 由大到小 排列
// result = Integer.compare(c1.nextPosSteps, c2.nextPosSteps);
}
return result;
}
};
//判断下一步是否回到起点
private static boolean isNextStepStartPoint(int x, int y) {
for (int i = 0; i < 8; i++) {
if (x + dx[i] == startX && y + dy[i] == startY)
return true;
}
return false;
}
private static void print(int n, int m) {
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++)
System.out.print(String.format("%4d", board[i][j]));
System.out.println();
}
if(board[1][1] != 1){
System.out.println("-------Change to start from (1,1)--------");
int tmpStart = board[1][1];
for(int i=1; i<=m; i++)
for(int j=1; j<=n; j++)
if(board[i][j] > tmpStart)
board[i][j] = board[i][j]-tmpStart+1;
else if(board[i][j] < tmpStart)
board[i][j] = board[i][j]+m*n-tmpStart+1;
else
board[i][j] = 1;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++)
System.out.print(String.format("%4d", board[i][j]));
System.out.println();
}
}
//参数x,y 表示棋盘的位置
//检测(x,y) 对应位置在棋盘中是否合法
private static boolean isNextStepOk(int x, int y) {
if (x < 1 || y < 1 || x > m || y > n || board[x][y] != 0)
return false;
else
return true;
}
//该处有效的下一步有多少种
private static int nextPossibleSteps(int x, int y){
int steps = 0;
for(int i=0; i<8; i++){
if(isNextStepOk(x+dx[i], y+dy[i]))
steps++;
}
return steps;
}
//距离棋盘中心点的距离
private static int currentToMidLength(int x, int y){
// int midX = 1;
// int midY = 1;
// int midX = m/2 - 1;
// int midY = n/2 - 1;
int midX = m/2;
int midY = n/2;
// int midX = m/2 + 1;
// int midY = n/2 + 1;
return (Math.abs(x-midX) + Math.abs(y-midY));
}
}
Output
25 50 3 60 23 48 55 44 21 46
4 61 24 49 64 59 22 47 56 43
51 26 63 2 69 54 65 58 45 20
62 5 70 53 98 67 102 117 42 57
27 52 99 68 1 118 111 66 19 104
6 71 28 97 110 101 120 103 116 41
29 86 73 100 119 112 115 90 105 18
72 7 96 85 94 109 106 113 40 91
83 30 87 74 107 114 89 92 17 78
8 33 84 95 88 93 108 79 14 39
31 82 35 10 75 80 37 12 77 16
34 9 32 81 36 11 76 15 38 13
-------Change to start from (1,1)--------
1 26 99 36 119 24 31 20 117 22
100 37 120 25 40 35 118 23 32 19
27 2 39 98 45 30 41 34 21 116
38 101 46 29 74 43 78 93 18 33
3 28 75 44 97 94 87 42 115 80
102 47 4 73 86 77 96 79 92 17
5 62 49 76 95 88 91 66 81 114
48 103 72 61 70 85 82 89 16 67
59 6 63 50 83 90 65 68 113 54
104 9 60 71 64 69 84 55 110 15
7 58 11 106 51 56 13 108 53 112
10 105 8 57 12 107 52 111 14 109
分治法(规模较大时)
Java
class grid {
int x;
int y;
}
public class Main {
private static int m = 20, n = 20;
private static grid[][] link = new grid[m][];
private static grid[] b66 = new grid[36];
private static grid[] b68 = new grid[48];
private static grid[] b86 = new grid[48];
private static grid[] b88 = new grid[64];
private static grid[] b810 = new grid[80];
private static grid[] b108 = new grid[80];
private static grid[] b1010 = new grid[100];
private static grid[] b1012 = new grid[120];
private static grid[] b1210 = new grid[120];
public static void main(String[] args) {
knight(m, n);
out();
}
private static void knight(int mm, int nn) {
int i, j, k;
int m = mm;
int n = nn;
//循环,初始化操作
//一定要加入该循环,进行初始化,不然b66里面全部为null
for (i = 0; i < 36; i++) {
b66[i] = new grid();
}
for (i = 0; i < 48; i++) {
b68[i] = new grid();
}
for (i = 0; i < 48; i++) {
b86[i] = new grid();
}
for (i = 0; i < 64; i++) {
b88[i] = new grid();
}
for (i = 0; i < 80; i++) {
b810[i] = new grid();
}
for (i = 0; i < 80; i++) {
b108[i] = new grid();
}
for (i = 0; i < 100; i++) {
b1010[i] = new grid();
}
for (i = 0; i < 120; i++) {
b1012[i] = new grid();
}
for (i = 0; i < 120; i++) {
b1210[i] = new grid();
}
//初始化二维数组link
for (k = 0; k < m; k++) {
link[k] = new grid[n];
for (i = 0; i < n; i++) {
link[k][i] = new grid();//一定要加上该句,才能初始化,不然link里面全部为null
}
}
//初始化二维数组a
int[][] a = new int[10][];
for (k = 0; k < 10; k++) {
a[k] = new int[12];
}
Make2DArray2(link, m, n);
Make2DArray1(a, 10, 12);
int[][] a66 = {
{1, 30, 33, 16, 3, 24},
{32, 17, 2, 23, 34, 15},
{29, 36, 31, 14, 25, 4},
{18, 9, 6, 35, 22, 13},
{7, 28, 11, 20, 5, 26},
{10, 19, 8, 27, 12, 21},
};
for (i = 0; i < 6; i++)
for (j = 0; j < 6; j++)
a[i][j] = a66[i][j];
change(6, 6, a, b66);
int[][] a68 = {
{1, 10, 31, 40, 21, 14, 29, 38},
{32, 41, 2, 11, 30, 39, 22, 13},
{9, 48, 33, 20, 15, 12, 37, 28},
{42, 3, 44, 47, 6, 25, 18, 23},
{45, 8, 5, 34, 19, 16, 27, 36},
{4, 43, 46, 7, 26, 35, 24, 17}
};
for (i = 0; i < 6; i++)
for (j = 0; j < 8; j++)
a[i][j] = a68[i][j];
change(6, 8, a, b68);
change(8, 6, a, b86);
int[][] a88 = {
{1, 46, 17, 50, 3, 6, 31, 52},
{18, 49, 2, 7, 30, 51, 56, 5},
{45, 64, 47, 16, 27, 4, 53, 32},
{48, 19, 8, 29, 10, 55, 26, 57},
{63, 44, 11, 22, 15, 28, 33, 54},
{12, 41, 20, 9, 36, 23, 58, 25},
{43, 62, 39, 14, 21, 60, 37, 34},
{40, 13, 42, 61, 38, 35, 24, 59}
};
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
a[i][j] = a88[i][j];
change(8, 8, a, b88);
int[][] a810 = {
{1, 46, 37, 66, 3, 48, 35, 68, 5, 8},
{38, 65, 2, 47, 36, 67, 4, 7, 34, 69},
{45, 80, 39, 24, 49, 18, 31, 52, 9, 6},
{64, 23, 44, 21, 30, 15, 50, 19, 70, 33},
{79, 40, 25, 14, 17, 20, 53, 32, 51, 10},
{26, 63, 22, 43, 54, 29, 16, 73, 58, 71},
{41, 78, 61, 28, 13, 76, 59, 56, 11, 74},
{62, 27, 42, 77, 60, 55, 12, 75, 72, 57}
};
for (i = 0; i < 8; i++)
for (j = 0; j < 10; j++)
a[i][j] = a810[i][j];
change(8, 10, a, b810);
change(10, 8, a, b108);
int[][] a1010 = {
{1, 54, 69, 66, 3, 56, 39, 64, 5, 8},
{68, 71, 2, 55, 38, 65, 4, 7, 88, 63},
{53, 100, 67, 70, 57, 26, 35, 40, 9, 6},
{72, 75, 52, 27, 42, 37, 58, 87, 62, 89},
{99, 30, 73, 44, 25, 34, 41, 36, 59, 10},
{74, 51, 76, 31, 28, 43, 86, 81, 90, 61},
{77, 98, 29, 24, 45, 80, 33, 60, 11, 92},
{50, 23, 48, 79, 32, 85, 82, 91, 14, 17},
{97, 78, 21, 84, 95, 46, 19, 16, 93, 12},
{22, 49, 96, 47, 20, 83, 94, 13, 18, 15}
};
for (i = 0; i < 10; i++)
for (j = 0; j < 10; j++)
a[i][j] = a1010[i][j];
change(10, 10, a, b1010);
int[][] a1012 = {
{1, 4, 119, 100, 65, 6, 69, 102, 71, 8, 75, 104},
{118, 99, 2, 5, 68, 101, 42, 7, 28, 103, 72, 9},
{3, 120, 97, 64, 41, 66, 25, 70, 39, 74, 105, 76},
{98, 117, 48, 67, 62, 43, 40, 27, 60, 29, 10, 73},
{93, 96, 63, 44, 47, 26, 61, 24, 33, 38, 77, 106},
{116, 51, 94, 49, 20, 23, 46, 37, 30, 59, 34, 11},
{95, 92, 115, 52, 45, 54, 21, 32, 35, 80, 107, 78},
{114, 89, 50, 19, 22, 85, 36, 55, 58, 31, 12, 81},
{91, 18, 87, 112, 53, 16, 57, 110, 83, 14, 79, 108},
{88, 113, 90, 17, 86, 111, 84, 15, 56, 109, 82, 13}
};
for (i = 0; i < 10; i++)
for (j = 0; j < 12; j++)
a[i][j] = a1012[i][j];
change(10, 12, a, b1012);
change(12, 10, a, b1210);
}
//二维数组的构造
private static void Make2DArray1(int[][] a, int m, int n) {
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
a[i][j] = 0;
}
private static void Make2DArray2(grid[][] link, int m, int n) {
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
link[i][j].x = 0;
link[i][j].y = 0;
}
}
//change用于将读入的基础棋盘的Hamilton回路转化为网格数据
private static void change(int m, int n, int[][] a, grid[] b) {
int i, j, k = m * n;
if (m < n) {
for (i = 0; i < m; i++)
for (j = 0; j < n; j++) {
int p = a[i][j] - 1;
b[p].x = i;
b[p].y = j;
}
} else {
for (i = 0; i < m; i++)
for (j = 0; j < n; j++) {
int p = a[j][i] - 1;
b[p].x = i;
b[p].y = j;
}
}
}
private static void out() {
int i, j, k, x, y, p;
int[][] a;
a = new int[m][];
for (k = 0; k < m; k++) {
a[k] = new int[n];
}
Make2DArray1(a, m, n);
if (comb(m, n, 0, 0)) return;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
a[i][j] = 0;
i = 0;
j = 0;
k = 2;
a[0][0] = 1;
System.out.print(" (0,0) ");
// System.out.print("(0,0) ");
for (p = 1; p < m * n; p++) {
x = link[i][j].x;
y = link[i][j].y;
i = x / n;
j = x % n;
if (a[i][j] > 0) {
i = y / n;
j = y % n;
}
a[i][j] = k++;
System.out.print(String.format("%8s", "(" + i + "," + j + ") "));
// System.out.print("(" + i + "," + j + ") ");
if ((k - 1) % n == 0)
System.out.println();
}
System.out.println();
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++)
System.out.print(String.format("%4d", a[i][j]));
// System.out.print(a[i][j] + " ");
System.out.println();
}
}
//分治法的主体由如下算法 comb 给出
private static boolean comb(int mm, int nn, int offx, int offy) {
int mm1, mm2, nn1, nn2;
int[] x = new int[8];
int[] y = new int[8];
int[] p = new int[8];
if (odd(mm) || odd(nn) || mm - nn > 2 || nn - mm > 2 || mm < 6 || nn < 6) return true;
if (mm < 12 || nn < 12)//基础解
{
base_answer(mm, nn, offx, offy);
return false;
}
mm1 = mm / 2;
if (mm % 4 > 0) mm1--;
mm2 = mm - mm1;
nn1 = nn / 2;
if (nn % 4 > 0) nn1--;
nn2 = nn - nn1;
//分割步
comb(mm1, nn1, offx, offy);
comb(mm1, nn2, offx, offy + nn1);
comb(mm2, nn1, offx + mm1, offy);
comb(mm2, nn2, offx + mm1, offy + nn1);
//合并步
x[0] = offx + mm1 - 1;
y[0] = offy + nn1 - 3;
x[1] = x[0] - 1;
y[1] = y[0] + 2;
x[2] = x[1] - 1;
y[2] = y[1] + 2;
x[3] = x[2] + 2;
y[3] = y[2] - 1;
x[4] = x[3] + 1;
y[4] = y[3] + 2;
x[5] = x[4] + 1;
y[5] = y[4] - 2;
x[6] = x[5] + 1;
y[6] = y[5] - 2;
x[7] = x[6] - 2;
y[7] = y[6] + 1;
for (int i = 0; i < 8; i++)
p[i] = pos(x[i], y[i], n);
for (int i = 1; i < 8; i += 2) {
int j1 = (i + 1) % 8, j2 = (i + 2) % 8;
if (link[x[i]][y[i]].x == p[i - 1]) link[x[i]][y[i]].x = p[j1];
else link[x[i]][y[i]].y = p[j1];
if (link[x[j1]][y[j1]].x == p[j2]) link[x[j1]][y[j1]].x = p[i];
else link[x[j1]][y[j1]].y = p[i];
}
return false;
}
//odd函数
private static boolean odd(int x) {
if (x % 2 == 0) return false;
else return true;
}
//base_answer是根据基础解构造子棋盘的结构化的Hamilton回路
private static void base_answer(int mm, int nn, int offx, int offy) {
if (mm == 6 && nn == 6) build(mm, nn, offx, offy, n, b66);
if (mm == 6 && nn == 8) build(mm, nn, offx, offy, n, b68);
if (mm == 8 && nn == 6) build(mm, nn, offx, offy, n, b86);
if (mm == 8 && nn == 8) build(mm, nn, offx, offy, n, b88);
if (mm == 8 && nn == 10) build(mm, nn, offx, offy, n, b810);
if (mm == 10 && nn == 8) build(mm, nn, offx, offy, n, b108);
if (mm == 10 && nn == 10) build(mm, nn, offx, offy, n, b1010);
if (mm == 10 && nn == 12) build(mm, nn, offx, offy, n, b1012);
if (mm == 12 && nn == 10) build(mm, nn, offx, offy, n, b1210);
}
//实质性的构造由算法build完成
private static void build(int m, int n, int offx, int offy, int col, grid[] b) {
int i, p, q, k = m * n;
for (i = 0; i < k; i++) {
int x1 = offx + b[i].x, y1 = offy + b[i].y;
int x2 = offx + b[(i + 1) % k].x, y2 = offy + b[(i + 1) % k].y;
p = pos(x1, y1, col);
q = pos(x2, y2, col);
link[x1][y1].x = q;
link[x2][y2].y = p;
}
}
//pos用于表示计算棋盘方格的编号,棋盘方格各行从上到下,各列从左到右依次编号为0,1....,mn-1
private static int pos(int x, int y, int col) {
return col * x + y;
}
}
Output
(0,0) (2,1) (4,0) (6,1) (8,0) (9,2) (7,1) (9,0) (8,2) (9,4) (8,6) (9,8) (7,9) (8,7) (9,9) (7,8) (9,7) (10,9) (11,7) (13,6)
(14,4) (15,2) (13,3) (14,5) (12,6) (11,4) (13,5) (14,7) (16,6) (15,4) (16,2) (17,4) (15,3) (14,1) (16,0) (17,2) (16,4) (14,3) (15,5) (13,4)
(14,6) (15,8) (13,9) (12,7) (11,9) (10,7) (11,5) (12,3) (10,2) (11,0) (13,1) (15,0) (14,2) (16,3) (18,4) (17,6) (19,5) (18,3) (19,1) (17,0)
(15,1) (13,0) (12,2) (10,1) (12,0) (13,2) (11,1) (10,3) (12,4) (10,5) (11,3) (12,5) (10,6) (11,8) (13,7) (15,6) (17,5) (16,7) (15,9) (13,8)
(15,7) (16,5) (17,3) (18,1) (19,3) (18,5) (17,7) (19,6) (18,8) (16,9) (14,8) (12,9) (10,8) (11,6) (10,4) (11,2) (10,0) (12,1) (14,0) (16,1)
(18,0) (19,2) (17,1) (19,0) (18,2) (19,4) (18,6) (19,8) (17,9) (18,7) (19,9) (17,8) (19,7) (18,9) (16,8) (14,9) (12,8) (11,10) (13,11) (15,10)
(14,12) (16,13) (18,14) (17,16) (19,15) (18,13) (19,11) (17,10) (15,11) (13,10) (12,12) (10,11) (12,10) (13,12) (11,11) (10,13) (12,14) (10,15) (11,13) (12,15)
(10,16) (11,18) (13,17) (15,16) (17,15) (16,17) (15,19) (13,18) (15,17) (16,15) (17,13) (18,11) (19,13) (18,15) (17,17) (19,16) (18,18) (16,19) (14,18) (12,19)
(10,18) (11,16) (10,14) (11,12) (10,10) (12,11) (14,10) (16,11) (18,10) (19,12) (17,11) (19,10) (18,12) (19,14) (18,16) (19,18) (17,19) (18,17) (19,19) (17,18)
(19,17) (18,19) (16,18) (14,19) (12,18) (10,19) (11,17) (13,16) (14,14) (15,12) (13,13) (14,15) (12,16) (11,14) (13,15) (14,17) (16,16) (15,14) (16,12) (17,14)
(15,13) (14,11) (16,10) (17,12) (16,14) (14,13) (15,15) (13,14) (14,16) (15,18) (13,19) (12,17) (11,19) (10,17) (11,15) (12,13) (10,12) (9,10) (8,12) (9,14)
(8,16) (9,18) (7,19) (8,17) (9,19) (7,18) (9,17) (8,19) (6,18) (4,19) (2,18) (0,19) (1,17) (3,16) (4,14) (5,12) (3,13) (4,15) (2,16) (1,14)
(3,15) (4,17) (6,16) (5,14) (6,12) (7,14) (5,13) (4,11) (6,10) (7,12) (6,14) (4,13) (5,15) (3,14) (4,16) (5,18) (3,19) (2,17) (1,19) (0,17)
(1,15) (2,13) (0,12) (1,10) (3,11) (5,10) (4,12) (6,13) (8,14) (7,16) (9,15) (8,13) (9,11) (7,10) (5,11) (3,10) (2,12) (0,11) (2,10) (3,12)
(1,11) (0,13) (2,14) (0,15) (1,13) (2,15) (0,16) (1,18) (3,17) (5,16) (7,15) (6,17) (5,19) (3,18) (5,17) (6,15) (7,13) (8,11) (9,13) (8,15)
(7,17) (9,16) (8,18) (6,19) (4,18) (2,19) (0,18) (1,16) (0,14) (1,12) (0,10) (2,11) (4,10) (6,11) (8,10) (9,12) (7,11) (8,9) (6,8) (4,9)
(2,8) (0,9) (1,7) (3,6) (4,4) (5,2) (3,3) (4,5) (2,6) (1,4) (3,5) (4,7) (6,6) (5,4) (6,2) (7,4) (5,3) (4,1) (6,0) (7,2)
(6,4) (4,3) (5,5) (3,4) (4,6) (5,8) (3,9) (2,7) (1,9) (0,7) (1,5) (2,3) (0,2) (1,0) (3,1) (5,0) (4,2) (6,3) (8,4) (7,6)
(9,5) (8,3) (9,1) (7,0) (5,1) (3,0) (2,2) (0,1) (2,0) (3,2) (1,1) (0,3) (2,4) (0,5) (1,3) (2,5) (0,6) (1,8) (3,7) (5,6)
(7,5) (6,7) (5,9) (3,8) (5,7) (6,5) (7,3) (8,1) (9,3) (8,5) (7,7) (9,6) (8,8) (6,9) (4,8) (2,9) (0,8) (1,6) (0,4) (1,2)
1 368 353 372 399 374 377 350 397 322 311 278 263 282 309 284 287 260 307 232
354 371 400 375 330 351 398 323 378 349 264 281 310 285 240 261 308 233 288 259
369 2 367 352 373 376 329 348 321 396 279 312 277 262 283 286 239 258 231 306
366 355 370 327 344 331 324 379 384 347 276 265 280 237 254 241 234 289 294 257
3 338 357 342 325 328 345 332 395 320 313 248 267 252 235 238 255 242 305 230
356 365 326 337 334 343 380 385 346 383 266 275 236 247 244 253 290 295 256 293
339 4 335 358 341 386 333 382 319 394 249 314 245 268 251 296 243 292 229 304
364 7 340 387 336 381 360 391 16 13 274 317 250 297 246 291 270 301 226 223
5 388 9 362 359 390 11 14 393 318 315 298 219 272 269 300 221 224 303 228
8 363 6 389 10 361 392 17 12 15 218 273 316 299 220 271 302 227 222 225
97 64 49 68 95 70 73 46 93 18 165 132 217 136 163 138 141 214 161 186
50 67 96 71 26 47 94 19 74 45 118 135 164 139 194 215 162 187 142 213
65 98 63 48 69 72 25 44 117 92 133 166 131 216 137 140 193 212 185 160
62 51 66 23 40 27 20 75 80 43 130 119 134 191 208 195 188 143 148 211
99 34 53 38 21 24 41 28 91 116 167 202 121 206 189 192 209 196 159 184
52 61 22 33 30 39 76 81 42 79 120 129 190 201 198 207 144 149 210 147
35 100 31 54 37 82 29 78 115 90 203 168 199 122 205 150 197 146 183 158
60 103 36 83 32 77 56 87 112 109 128 171 204 151 200 145 124 155 180 177
101 84 105 58 55 86 107 110 89 114 169 152 173 126 123 154 175 178 157 182
104 59 102 85 106 57 88 113 108 111 172 127 170 153 174 125 156 181 176 179
Reference
王晓东《计算机算法设计与分析》(第3版)P42-43