问题描述
一个8×8的棋盘上有一个马初始位置为(a,b),他想跳到(c,d),问是否可以?如果可以,最少要跳几步?
输入格式:
一行四个数字a,b,c,d。
输出格式:
如果跳不到,输出-1;否则输出最少跳到的步数。
样例输入:
1 1 2 3
样例输出:
1
数据规模和约定:
0<a,b,c,d≤8且都是整数。
思路:
用深度优先遍历(DFS)搜索每一种可能到达的情况。
我们熟知马在象棋中只能走“日”,因此:
对于当前坐标x、y的变化共有8种情况:
(1,2)(1,-2)(-1,-2)(-1,2)(2,-1)(2,1)(-2,-1)(-2,1)
完整代码:
import java.util.Scanner;
public class Main {
static int c,d; // 对于不变的数据可以定义为全局变量,便于访问
static int[] dx = new int[]{1,1,-1,-1,2,2,-2,-2}; // 8种状态
static int[] dy = new int[]{2,-2,2,-2,1,-1,1,-1};
static boolean[][] visit = new boolean[9][9]; // 用来判断当前坐标是否访问过
static int step = 64; // 最大步数不可能超过64
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
c = sc.nextInt();
d = sc.nextInt();
solve(a,b,0);
step = step==64?-1:step; // 若step为发生改变,则没有方案到达,应输出-1;
System.out.println(step);
}
/**
* @param a 当前横坐标
* @param b 当前纵坐标
* @param st 当前走的步数
*/
private static void solve(int a, int b, int st) {
if (a<=0||a>8||b<=0||b>8||visit[a][b]||st>=step)
return; // 若越界或者已访问过,则返回;当前步数若已大于已找到的步数,则返回,减少工作量
if (a==c&&b==d){
step = Math.min(step,st); //满足要求时,返回当前步数和已找到方案的步数的较小值
return;
}
visit[a][b]=true; // 访问了的坐标标记为true
for (int i=0;i<8;i++){
solve(a+dx[i],b+dy[i],st+1); // DFS
}
visit[a][b]=false; // 回溯
}
}