• 深度优先搜索(Depth-First-Search)精髓


    引例:迷宫问题 
    首先我们来想象一只老鼠,在一座不见天日的迷宫内,老鼠在入口处进去,要从出口出来。那老鼠会怎么走?当然可以是这样的:老鼠如果遇到直路,就一直往前走,如果遇到分叉路口,就任意选择其中的一条继续往下走,如果遇到死胡同,就退回到最近的一个分叉路口,选择另一条道路再走下去,如果遇到了出口,老鼠的旅途就算成功结束了。 
     
    深度优先搜索的基本原则就是这样:按照某种条件往前试探搜索,如果前进中遭到失败(正如老鼠遇到死胡同)则退回头另选通路继续搜索,直到找到满足条件的目标为止。  
    递归程序设计 
    然而要实现这样的算法,我们需要用到编程的一大利器---递归。当一个函数直接或者间接的调用了自己本身的时候,则发生了递归。 
    讲一个更具体的例子:从前有座山,山里有座庙,庙里有个老和尚,老和尚在讲故事,讲什么呢?讲:从前有座山,山里有座庙,庙里有个老和尚,老和尚在讲故事,讲什么呢?讲:从前有座山,山里有座庙,庙里有个老和尚,老和尚在讲故事,讲什么呢?讲:„„„„。好家伙,这样讲到世界末日还讲不玩,老和尚讲的故事实际上就是前面的故事情节,这样不断地调用程序本身,就形成了递归。万一这个故事中的某一个老和尚看这个故事不顺眼,就把他要讲的故事换成:“你有完没完啊!”,这样,整个故事也就嘎然而止了。

    我们编程就要注意这一点,在适当的时候,就必须要有一个这样的和尚挺身而出,把整个故事给停下来,或者说他不再往深一层次搜索,要不,我们的递归就会因计算机栈空间大小的限制而溢出,称为stack overflow。  
    递归的经典实例: 

    int factorial(int n) { 
       if (n == 0//基线条件(base case)    
        { 
          return 1;    
        } else
        { 
          return n * factorial(n - 1);    //将问题规模逐渐缩小,或者说转化为更小                              更简单的子问题      
        } 
    }                                                        

    引入DFS 水仙花数: 
    一个三位数abc如果满足abc = a^3 + b^3 + c^3 那么就把

    这个数叫做水仙花数,写一个程序,求出所有的水仙花数。  
    广义水仙花数: 
    如果一个N位数所有数码的N次方的和加起来等于这个数字本身,我们把这样的数叫做广义水仙花数,容易看出来水仙花数是N = 3的广义水仙花数现在,我们的任务是,输入一个m (m < 7) ,让你求出所有满足N = m的广义水仙花数。 3 (153 370 371 407) 5 (54748 92727 93084) 
    方法:数据规模很小,可以直接枚举所有情况,然后判断是否满足条件。 难点:循环层数不确定  
    于是我们现在的问题是,怎么实现这个m重循环?

    答案是:递归。  
    m重循环的实现:

    void dfs(int deep){
          if (deep > m) 
         {   //check answer 
         } 
         else if (deep <= m)
          {
               for (i = 1; i <= n; i++)    
                    dfs(deep + 1);  
            } 
    }      

    没错,这个就是深度优先搜索(Depth-First-Search),那么它为什么叫DFS呢?这就是我下面要讲的:  
    1、搜索树就是,搜索过程中所形成的树形结构。(图) 
    2、很容易发现,DFS我们在计算那个问题的时候,总是尽量往深里走,也就是说 深度比广度 优先,所以这种方法叫做深度优先搜索。 
    3、同样,如果我们一层一层搜索,这样,它的广度先得到了扩展,就叫做广度优先搜索(Breadth-First-Search, BFS)。  
    深度优先搜索解决问题的框架

    void dfs(int deep, State curState) {
          if (deep > Max) //深度达到极限
          {   
                if (curState == target) //找到目标
               {    //... 
               } 
          } else{
                      for (i = 1; i <= totalExpandMethod; i++) 
                     {   
                          dfs(deep 1, expandMethod(curState, i));  
                     } 
          }
    }                                                                          
  • 相关阅读:
    Sitecore安全:访问权限
    Sitecore 8.2 防火墙规则的权威指南
    Sitecore 8.2 安全性第2部分:安全性编辑器和Access Viewer
    Sitecore安全性第1部分:自定义角色和权限
    Sitecore 8.2 Admin用户帐户解锁
    Sitecore 8.2 数据库权限设置
    cesium 结合 geoserver 实现地图属性查询(附源码下载)
    Vue&Cesium&Ribbon界面: 将桌面GIS搬进浏览器
    leaflet图斑历史时空播放(附源码下载)
    openlayers6结合geoserver实现地图属性查询(附源码下载)
  • 原文地址:https://www.cnblogs.com/li303491/p/4108991.html
Copyright © 2020-2023  润新知