5-12 罗密欧与朱丽叶的迷宫问题
问题描述
罗密欧与朱丽叶的迷宫。罗密欧与朱丽叶身处一个 m×n 的迷宫中,如图所示。每一个方格表示迷宫中的一个房间。这 m×n 个房间中有一些房间是封闭的,不允许任何人进入。 在迷宫中任何位置均可沿 8 个方向进入未封闭的房间。罗密欧位于迷宫的(p,q)方格中,他 必须找出一条通向朱丽叶所在的(r,s)方格的路。在抵达朱丽叶之前,他必须走遍所有未封 闭的房间各一次,而且要使到达朱丽叶的转弯次数为最少。每改变一次前进方向算作转弯一 次。请设计一个算法帮助罗密欧找出这样一条道路。
对于给定的罗密欧与朱丽叶的迷宫,编程计算罗密欧通向朱丽叶的所有最少转弯道路。
数据输入:
第一行有 3 个正整数 n,m,k,分别表示迷宫的行数,列数和封闭的房间数。接下来的 k 行中,每行 2 个正整数,表示被封闭的房间所在的行号和 列号。最后的 2 行,每行也有 2 个正整数,分别表示罗密欧所处的方格(p,q)和朱丽叶所处 的方格(r,s)。
Java
package Chapter5HuiSuFa;
import java.util.Scanner;
public class RomeoYuJulietDeMiGong {
private static int[] dx = {0,-1,-1,0,1,1,1,0,-1};
private static int[] dy = {0,0,1,1,1,0,-1,-1,-1};
private static int n,m,k;
private static int dirs,best,count;
private static int x,y,x1,y1;
private static int[][] board,bestb;
private static int MAX = 100000;
public static void main(String[] args){
Scanner input = new Scanner(System.in);
while (true){
best = MAX;
dirs = 0;
n = input.nextInt();
m = input.nextInt();
k = input.nextInt();
board = new int[n+1][m+1];
bestb = new int[n+1][m+1];
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
board[i][j] = 0;
for(int i=1; i<=k; i++){
int row = input.nextInt();
int col = input.nextInt();
board[row][col] = -1;
}
x = input.nextInt();
y = input.nextInt();
x1 = input.nextInt();
y1 = input.nextInt();
board[x][y] = 1;
//最开始只能向下走(1,0),本程序中即为(dx[5],dy[5]): x(行)增加,y(列)不变
//所以最开始的di设为5,不然方向会多一次比较,会多1
search(1,x,y,5);
System.out.println(best);
System.out.println(count);
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++)
System.out.print(bestb[i][j]+" ");
System.out.println();
}
}
}
private static void search(int dep, int x, int y, int di){
if(dep==m*n-k && x==x1 && y==y1 && dirs<=best){
if(dirs < best){
best = dirs;
count = 1;
save();
}else
count++;
return;
}
if(dep==m*n-k || x==x1 && y==y1 || dirs>best) return;
else
for(int i=1; i<=8; i++){
if(stepok(x+dx[i], y+dy[i])){
board[x+dx[i]][y+dy[i]] = dep+1;
if(di != i) dirs++;
search(dep+1,x+dx[i],y+dy[i],i);
if(di != i) dirs--;
board[x+dx[i]][y+dy[i]] = 0;
}
}
}
private static boolean stepok(int x, int y){
return (x>0 && x<=n && y>0 && y<=m && board[x][y]==0);
}
private static void save(){
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
bestb[i][j] = board[i][j];
}
}
Input & Output
3 4 2
1 2
3 4
1 1
2 2
6
7
1 -1 7 6
2 10 5 8
3 4 9 -1
Reference
王晓东《计算机算法设计与分析》(第3版)P183