力扣909. 蛇梯棋

广度优先搜索 + 动态规划

  • 思路:
    • 定义 pair {id, step} 为到达格子编号 id,使用的步数 step,记作 step[id];
    • 记录下所摇骰子 1 - 6 到达的格子编号 next,step[next] = step[id] + 1:
      • 走了 1 步,所能到达的编号;如果中途遇到传送门,直接更新 next 编号;
      • 使用一个数组记录编号是否已经被访问,如果被访问,本着使用步数最少,直接使用上次到达该位置的状态,往后摇骰子即可;
      • 编号没有被访问,则标记染色,同时更新状态 step[next];
    • 基于这些 step[id] 状态队列,广度优先搜索,动态更新状态,直到到达终点时停止;
    • 获取方格值,需要有一个编号到行列号的映射函数:
      • private:
            std::pair<int, int> id2rc(int id, int n) {
                int row = (id - 1) / n;
                int column = (id - 1) % n;
                if (row % 2 == 1) {
                    column = n - 1 - column;
                }
        
                return {n - 1 - row, column};
            }

      • n - 1 - row 是因为起点是从左下角开始;
      • 因为是左右盘桓,奇偶行的列号发生颠倒;
class Solution {
public:
    int snakesAndLadders(vector<vector<int>>& board) {
        int n = board.size();

        std::vector<int> visited(n * n + 1);

        std::queue<std::pair<int, int>> qu;
        qu.emplace(1, 0);
        while (!qu.empty()) {
            auto p = qu.front();
            qu.pop();

            for (int i = 1; i <= 6; ++i) {
                int next = p.first + i;
                if (next > n *n) {
                    break;
                }

                // update next row & column
                auto rc = id2rc(next, n);
                // gateway and passthrough to the dst
                if (board[rc.first][rc.second] > 0) {
                    next = board[rc.first][rc.second];
                }
                // final state
                if (next == n * n) {
                    return p.second + 1;
                }
                if (!visited[next]) {
                    visited[next] = true;
                    qu.emplace(next, p.second + 1);
                }
            }
        }

        return -1;
    }

private:
    std::pair<int, int> id2rc(int id, int n) {
        int row = (id - 1) / n;
        int column = (id - 1) % n;
        if (row % 2 == 1) {
            column = n - 1 - column;
        }

        return {n - 1 - row, column};
    }
};

  • 32
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值