蛇梯棋题解

题目链接909. 蛇梯棋 - 力扣(LeetCode)
题目描述

给定一个 N x N 的棋盘,棋盘的方格按从左下角开始的蛇形方式编号(从 1 开始到 NN)。棋盘中存在蛇和梯子,当玩家到达特定编号的格子时,会被传送到另一个格子。求玩家从起点(编号 1)移动到终点(编号 NN)所需的最少移动次数。

解题思路

这是一个典型的广度优先搜索(BFS)问题。BFS 适合求解最短路径问题,因为它逐层扩展状态,一旦找到目标状态,当前步数即为最短路径。

棋盘的特殊编号方式需要进行坐标转换:

  • 从编号到行列的转换需要考虑蛇形排列,即偶数行(从 0 开始)从左到右编号,奇数行从右到左编号。
  • 转换函数需要处理这种蛇形排列,确保正确映射到棋盘上的实际位置。
代码实现
#include <vector>
#include <queue>
using namespace std;

class Solution {
    // 将编号转换为棋盘上的行列坐标
    pair<int, int> convertToBoardPosition(int id, int boardSize) {
        int row = (id - 1) / boardSize;  // 计算所在行
        int col = (id - 1) % boardSize;  // 计算所在列
        
        // 处理蛇形排列:偶数行从左到右,奇数行从右到左
        if (row % 2 == 1) {
            col = boardSize - 1 - col;  // 奇数行需要反转列顺序
        }
        
        // 棋盘的行是从下往上数的,所以需要转换
        return {boardSize - 1 - row, col};
    }

public:
    int snakesAndLadders(vector<vector<int>>& board) {
        int n = board.size();  // 棋盘大小
        vector<bool> visited(n * n + 1, false);  // 记录每个位置是否已访问
        queue<pair<int, int>> bfsQueue;  // BFS队列,存储{当前位置, 步数}
        
        bfsQueue.push({1, 0});  // 从位置1开始,初始步数为0
        visited[1] = true;  // 标记起点为已访问
        
        while (!bfsQueue.empty()) {
            auto [currentPos, steps] = bfsQueue.front();
            bfsQueue.pop();
            
            // 尝试从当前位置移动1到6步
            for (int dice = 1; dice <= 6; ++dice) {
                int nextPos = currentPos + dice;
                
                // 如果超出棋盘范围,停止扩展
                if (nextPos > n * n) {
                    break;
                }
                
                // 转换为棋盘上的行列坐标
                auto [row, col] = convertToBoardPosition(nextPos, n);
                
                // 如果该位置有蛇或梯子,更新下一步位置
                if (board[row][col] != -1) {
                    nextPos = board[row][col];
                }
                
                // 如果到达终点,返回当前步数+1
                if (nextPos == n * n) {
                    return steps + 1;
                }
                
                // 如果下一步位置未访问过,加入队列并标记为已访问
                if (!visited[nextPos]) {
                    visited[nextPos] = true;
                    bfsQueue.push({nextPos, steps + 1});
                }
            }
        }
        
        // 无法到达终点
        return -1;
    }
};
代码解释
  1. convertToBoardPosition 函数:将编号转换为棋盘上的行列坐标,处理蛇形排列的特殊规则。
  2. visited 数组:记录每个位置是否已被访问,避免重复处理。
  3. BFS 队列:使用队列进行广度优先搜索,每个元素包含当前位置和到达该位置的步数。
  4. 主循环:每次从队列中取出当前位置,尝试所有可能的移动(1 到 6 步),处理蛇和梯子的跳转,更新队列。

通过这种方式,我们可以高效地找到从起点到终点的最短路径,或者确定无法到达终点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.wei-upup

如若对您有用,盼您赏个鼓励~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值