骑士的移动(Knight Moves, Uva439)- BFS模板题

博客介绍了如何运用广度优先搜索(BFS)算法求解国际象棋马从起点到终点的最短移动步数。通过解析输入的坐标,建立棋盘状态并用队列进行BFS搜索。在遍历过程中,更新距离并标记已访问位置,最终找到最短路径。代码中特别提到了一个可能导致错误的地方,即状态存储不能直接用int数组,而应使用动态分配的int指针数组,以避免地址覆盖的问题。博客提供了多个测试用例并展示了正确输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

  • 参考网址:https://vjudge.net/problem/UVA-439
  • 大意:
    按照国际象棋🐴的移动规则,求🐴最小需要多少步从起点跳到终点。(老BFS模板题了~)

知识点

  • BFS求最短路径

思路

BFS模板题,输入转换为坐标r (row),c (column)行和列,使用队列的方式进行BFS,使用vis记录是否访问,使用dis记录距离(当然两个可以合并为一个来写)。

  • 每次pop出队首u检查是否是目的位置,是的话返回当前节点位置所记录下的dis。
  • 否则,向“四面八方”扩散出去,判断条件为即不超出边界,且没有访问过 (is_ok(r1, c1) && !vis[r1][c1])。(访问过再走一边相当于绕圈子了,肯定不是最短路径)如果满足条件,将该状态所在的位置的dis更新为dis[u] + 1(距离+1),vis[当前位置]打上标记然后入队,每次循环检查队列是否为空,如果队列为空,仍然没有找到目的位置,则说明无解(当然这道题是不可能有无解的)。
  • 状态的记录建议用个结构体,我用了数组记录,debug了半天,问题在后续有记录!!

代码

# include <iostream>
# include <queue>

using namespace std;

string alphabet = "abcdefg";  // 用于映射 0-7
int end_r, end_c;  // 结束坐标
int dr[] = {
   
   1, 2, 2, 1, -1, -2, -2, -1};  // 顺时针
int dc[] = {
   
   -2, -1, 1, 2, 2, 1, -1, -2};
int vis[8][8], dis[8][8];  // 记录访
"Knight moves"是指国际象棋中的“马”走法,即一步可以跳过一个正方形格,然后向左、右、上或下两个方向再跳一格,形成“L”形移动。在Java中,你可以通过模拟这种规则来实现一个骑士移动函数。以下是一个简单的示例: ```java public class KnightMove { public static boolean isLegalMove(int x1, int y1, int x2, int y2, int boardSize) { // 骑士的合法移动范围:(x, y) -> (x±2, y±1)(x±1, y±2) if (Math.abs(x1 - x2) == 2 && Math.abs(y1 - y2) == 1 || Math.abs(x1 - x2) == 1 && Math.abs(y1 - y2) == 2) { return true; } else if (x1 >= 0 && x1 < boardSize && y1 >= 0 && y1 < boardSize && x2 >= 0 && x2 < boardSize && y2 >= 0 && y2 < boardSize) { // 确保不在边界外 return true; } return false; } public static void move(int[][] chessBoard, int startRow, int startCol, int endRow, int endCol) { if (isLegalMove(startRow, startCol, endRow, endCol, chessBoard.length)) { System.out.println("Valid knight move from (" + startRow + ", " + startCol + ") to (" + endRow + ", " + endCol + ")"); } else { System.out.println("Invalid knight move."); } } // 示例用法 public static void main(String[] args) { int[][] board = new int[8][8]; move(board, 1, 2, 6, 5); // 骑士(1, 2)移到(6, 5),这是一个合法的步骤 move(board, 0, 0, 8, 8); // 越界无效移动 } } ``` 这个`KnightMove`类包含了判断骑士是否能从一个位置移动到另一个位置的`isLegalMove`方法,以及显示移动结果的`move`方法。在`main`函数中,你可以测试不同的坐标对。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值