909. 蛇梯棋 --leetcode--c#

题目描述:

在一块 N x N 的棋盘 board 上,从棋盘的左下角开始,每一行交替方向,按从 1 到 N*N 的数字给方格编号。例如,对于一块 6 x 6 大小的棋盘,可以编号如下:


玩家从棋盘上的方格 1 (总是在最后一行、第一列)开始出发。

每一次从方格 x 起始的移动都由以下部分组成:


    你选择一个目标方块 S,它的编号是 x+1,x+2,x+3,x+4,x+5,或者 x+6,只要这个数字 <= N*N。
    如果 S 有一个蛇或梯子,你就移动到那个蛇或梯子的目的地。否则,你会移动到 S。 


在 r 行 c 列上的方格里有 “蛇” 或 “梯子”;如果 board[r][c] != -1,那个蛇或梯子的目的地将会是 board[r][c]。

注意,你每次移动最多只能爬过蛇或梯子一次:就算目的地是另一条蛇或梯子的起点,你也不会继续移动。

返回达到方格 N*N 所需的最少移动次数,如果不可能,则返回 -1。

示例:

输入:[
[-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1],
[-1,35,-1,-1,13,-1],
[-1,-1,-1,-1,-1,-1],
[-1,15,-1,-1,-1,-1]]
输出:4
解释:
首先,从方格 1 [第 5 行,第 0 列] 开始。
你决定移动到方格 2,并必须爬过梯子移动到到方格 15。
然后你决定移动到方格 17 [第 3 行,第 5 列],必须爬过蛇到方格 13。
然后你决定移动到方格 14,且必须通过梯子移动到方格 35。
然后你决定移动到方格 36, 游戏结束。
可以证明你需要至少 4 次移动才能到达第 N*N 个方格,所以答案是 4。


 

提示:


    2 <= board.length = board[0].length <= 20
    board[i][j] 介于 1 和 N*N 之间或者等于 -1。
    编号为 1 的方格上没有蛇或梯子。
    编号为 N*N 的方格上没有蛇或梯子。

此题常规解法是把二维数组转成一维数组,进行bfs(广度优先搜索)。

转一维数组时需要注意从行尾查,偶数行需要从后往前。

上c#代码:

       public static int SnakesAndLadders(int[][] board)
        {
            int n = board.Length;
            List<int> myBoard = new List<int>(); //把board转成一维数组
            int curNumOfRow = 0;
            for (int i = n - 1; i >= 0; i--)
            {
                curNumOfRow++;
                if (curNumOfRow % 2 == 0) //从行尾计算,偶数行需要反转列
                {
                    for (int j = n - 1; j >= 0; j--)
                    {
                        myBoard.Add(board[i][j]);
                    }
                }
                else
                {
                    for (int j = 0; j < n; j++)
                    {
                        myBoard.Add(board[i][j]);
                    }
                }
            }

            int len = n * n;
            int[] visited = new int[len + 1]; //访问记录数组
            Queue<int[]> q = new Queue<int[]>(); //访问队列
            q.Enqueue(new int[] { 1, 0 }); //起始点添加到队列中,step = 0
            visited[1] = 1; //标记
            while (q.Count > 0)
            {
                int[] d = q.Dequeue();
                int node = d[0];  //取出当前点
                int step = d[1];  //取出当前步数

                for (int i = 1; i <= 6; i++)
                {
                    if (node + i > len) break; //超长返回

                    int next = myBoard[node + i - 1] == -1 ? node + i : myBoard[node + i - 1]; //如果有梯子或蛇就移动到其蛇或梯子的目的地,否则移动到node+i
                    if (next == len) return step + 1; //到达目的地了,返回步数

                    if (visited[next] == 0) //此点没有访问过
                    {
                        q.Enqueue(new int[] { next, step + 1 }); //加入到访问队列中(也就是向前走一步)
                        visited[next] = 1; //标记
                    }
                }
            }
            return -1;
        }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值