题目描述
有一个n*m的棋盘(1<n,m<=400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步
输入
一行四个数据,棋盘的大小和马的坐标
输出
一个n*m的矩阵,代表马到达某个点最少要走几步(中间的数用空格分开)
样例输入
3 3 1 1
样例输出
0 3 2
3 -1 1
2 1 4
好久没更新博客了,这段时间偷懒在玩游戏,部分学习笔记写了也没有放到博客。主要原因是写博客要排版比较麻烦。今天学习广度优先搜索,碰到了这题,搞了大半天才解决。
思路:
若红点为马,可以往上下左右8个方向走动。
假设马的位置为(4,4) 那么可以走的位置是
所以,马的位置定义一个二维数组里,设当前点坐标为(sn,sm),这8个点可以这样来
static int point[][] = {{2,1},{1,2},{2,-1},{1,-2},{-2,-1},{-1,-2},{-1,2},{-2,1}};
for (int i = 0; i < 8; i++) //尝试向八个方向走
{
int x = sn + point[i][0];
int y = sm + point[i][1];
if(check(x,y)) //检查这坐标能不能去
{
....
}
}
定义棋盘数组chess[][],全部初始化为-1,定义horse()函数从起点开始遍历八个方向可以走的点,加入队列中,(还没接触到java队列数据结构。队列我用了另外一个二维数组queue[][]存放了),再遍历队列里的方向。最后输出结果。
毕竟第一次搞bfs,代码写得还是有点累赘。
import java.util.Scanner;
public class Main {
static int chess[][]; //定义一个棋盘数组n*m
static int n,m; //行与列
static int sn,sm; //马的第一个落脚点的xy坐标
static int point[][] = {{2,1},{1,2},{2,-1},{1,-2},{-2,-1},{-1,-2},{-1,2},{-2,1}};
//用于指向马的下一步位置,马向8个方向走的坐标
static int queue[][]; //用二维数组定义一个队列,存放x,y坐标及步数step
static int front,rear; //队列头部和尾部指针
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
n = in.nextInt(); m = in.nextInt(); sn = in.nextInt(); sm = in.nextInt();
chess = new int[n+1][m+1]; //坐标点从1,1开始计算
queue = new int[n*m][3]; //定义马走过步数的队列,最大入列数为n*m。存放x,y坐标及步数step
for (int i = 1; i <= n; i++) //将棋盘初始化全为-1
{
for (int j = 1; j <= m; j++)
{
chess[i][j] = -1;
}
}
chess[sn][sm] = 0; //马最初点的步数为0
queue[rear][0] = sn; //将马最初点装进队列,准备循环
queue[rear][1] = sm;
queue[rear][2] = 0;
rear++; //装进队列后,队列尾移动一位
do{
int temp = rear; //将当前的对尾放入temp,因为horse函数会添加数据导致改变队尾
for (int i = front; i < temp; i++) { //有多少个步数一样数据就循环多少次
horse(queue[i][0],queue[i][1],queue[i][2]); //马在当期坐标尝试向八个方向走,如果可以走就入队列
front++; //出队列,头部移动一位
}
}while(front != rear); //当队列头部和尾部相同说明已经完了
for (int i = 1; i <= n; i++) { //打印棋盘结果
for (int j = 1; j <= m; j++) {
System.out.print(chess[i][j] + " ");
}
System.out.println();
}
}
static void horse(int sn, int sm, int step) //马在当期坐标(sn,sm)尝试向八个方向走,如果可以走就入队列
{
for (int i = 0; i < 8; i++) //尝试向八个方向走
{
int x = sn + point[i][0];
int y = sm + point[i][1];
if(check(x,y)) //检查这坐标能不能去
{
chess[x][y] = ++step; //步数加1
queue[rear][0] = x; //入队列
queue[rear][1] = y;
queue[rear][2] = ++step;
rear++;
}
}
}
static boolean check(int sn, int sm) //检查这坐标能不能去
{
if(sn<1 || sn>n || sm<1 || sm>m)
{
return false;
}
if(chess[sn][sm] != -1)
{
return false;
}
return true;
}
}