深度优先搜索----解决有效路径查找问题

深度优先搜索----解决有效路径查找问题

一、问题地址:点击

二、算法分析与实现

  1. 概要分析

​ 题目要求是从左上角的网格开始找出一条能够到右下角网格的可达的路径,可以看出是明显的搜索问题,由于是找到一条可达的路径即可,因此采用DFS即可实现。

  1. 详细分析

​ 由于不同类型的网格出入口不同,因此在搜索时不能单纯的上下左右位移,需要考虑当前网格的出口和下一网格的入口是否能够对接,因此我们需要存储不同网格的出入口和能够与之对接的网格类型。因此设置如下存储结构:

_out <int, char[]>:字典类型,用于存储不同类型网格分别对应的可出位置(l:左 r:右 u:上 b:下)。

keyValues <char, int[]>:字典类型,用于存储不同出口对应的可对接网格

_mvIndex <char, int>:字典类型,用于存储走出相应的出口对应的位移矩阵索引。

算法工作流程:

(1)从当前(开始时是左上角网格)网格开始,将当前网格标记为已经经过状态,通过网格类型从_out中找出当前网格支持的出口集合

(2)遍历当前网格出口集合,并通过_mvIndex集合从相应的出口位移到下一网格,通过keyValues 检查下一网格是否与当前出口对接。

(3)如果对接,则检查当前网格是否是终点网格,是的话放回true即可,否则重复(1),直到搜索结束或达到无法继续搜索的状态。

    public class AlgorithmCenter200716
    {
        //不同出口可行方案
        private static Dictionary<char, int[]> keyValues = new Dictionary<char, int[]>();
        //出口
        private static Dictionary<int, char[]> _out = new Dictionary<int, char[]>();
        //位移矩阵索引
        private static Dictionary<char, int> _mvIndex = new Dictionary<char, int>();
        
        private int[,] _status;
        static AlgorithmCenter200716()
        {
            _out.Add(1, new char[] { 'l', 'r' });
            _out.Add(2, new char[] { 'u', 'b' });
            _out.Add(3, new char[] { 'l', 'b' });
            _out.Add(4, new char[] { 'r', 'b' });
            _out.Add(5, new char[] { 'l', 'u' });
            _out.Add(6, new char[] { 'r', 'u' });

            int[] al = new int[] { 1, 4, 6 };
            int[] ar = new int[] { 1, 3, 5 };
            int[] au = new int[] { 2, 3, 4 };
            int[] ab = new int[] { 2, 5, 6 };            
            keyValues.Add('l', al);
            keyValues.Add('r', ar);
            keyValues.Add('u', au);
            keyValues.Add('b', ab);

            _mvIndex.Add('l',3);
            _mvIndex.Add('r',1);
            _mvIndex.Add('u',0);
            _mvIndex.Add('b',2);

        }

        /// <summary>
        /// https://leetcode-cn.com/problems/check-if-there-is-a-valid-path-in-a-grid/
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        public bool HasValidPath(int[][] grid)
        {
            _status = new int[grid.GetLength(0),grid[0].Length];
            return Dfs(0,0,grid);
        }

        public bool Dfs(int x,int y,int[][] temp)
        {
            //将当前的单元格设置为走过
            _status[x,y] = 1;
            //如果发现已经到达目的单元格,则直接返回
            if (x == temp.GetLength(0) - 1 && y == temp[x].Length - 1)
                return true;

            //上下左右位移矩阵
            int[] xmv = {-1, 0, 1, 0 };
            int[] ymv = { 0, 1, 0, -1};
            
            //根据当前单元格类型获取出口集合
            _out.TryGetValue(temp[x][y],out char[] outTemp);
            //遍历所有出口寻找可移动的下一个单元格
            foreach (char c in outTemp)
            {
                //获取从当前出口移动到下一单元格的位移
                _mvIndex.TryGetValue(c, out int index);
                //计算下一单元格坐标
                int dx = x + xmv[index];
                int dy = y + ymv[index];

                //判断坐标是否满足条件
                if (dx >= 0 && dx < temp.GetLength(0) && dy >= 0 && dy < temp[dx].Length && _status[dx, dy] != 1)
                {
                    //获取从当前单元格可以出去的下一单元格类型
                    keyValues.TryGetValue(c, out int[] res);
                    //检查下一单元格的类型是否在满足的单元格类型集合内
                    foreach (int n in res)
                    {
                        if (temp[dx][dy] == n)
                        {
                            //如果在的话,则继续深度行走
                            if (Dfs(dx, dy, temp))
                                return true;
                        }
                    }

                }
            }
            
            return false;
        }

    }
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

浪舟子

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值