zoukankan      html  css  js  c++  java
  • BFS的小结

    写这类搜索题。首先感觉要有个框架。比如我的框架对于BFS来说(对于DFS,我想有两个一个是递归版一个是栈版)。这里是BFS小结。所以介绍一下BFS。我的框架。(也是搜集了网上许多神人的作品。)

    1:节点的定义。时间问题。步数。以及一系列其他基本动态属性都放在这里。先定义2个node now和next。

    2:map map本身就可以简单地记录可以行走和不可以行走的单纯点。(因为有些还有条件点。)map一开始在外面围一圈不可行走的属性。(这个也是仿照某位大神)这个围一圈直接在初始化的时候全部都是非法的  然后在scanf的时候保留即可。方便快捷。

    3:mark 这个标记数组可有可无。假如map不够用的时候加入。记得初始化!

    4:dir 我觉得dir真的是很重要。很多不同的走法其实都可以放入在dir之中。根据不同的情况有不同的方向的走法。

    5:flag,now的初始化。

    框架成熟之后是注意点(搜索的题目往往代码量较大。所以这一点是很重要的):

    1:队列清空问题!(有可能上一个测试例中会有残留)

    2:终点和可行走点(我喜欢在now的时候判断。即。即使遇到终点也加入队列中取出来的时候统一判断)。

    终点和可行走点都是可以加入的,所以我们总是放在一起。一个判断。但是当标记为不可行走的时候。终点假设是X。也被标记成了不可行走(用map标记的时候)。

    所以永远都是No!所以在里面还要特判一下加入。比如以下.是可行走。X是终点。

                    if(map[next.x][next.y]=='.'||map[next.x][next.y]=='X')
                    {
                        que.push(next);
                        if(map[next.x][next.y]=='.'){map[next.x][next.y] ='W';}
                    }
    View Code

    3:next的赋值。请确保每一项都确定过!。

    。。。(我还是新手待填充)

    一系列不同问题:

    1:相同区域个数。(DFS)

    2:目标查找。(DFS)

    3:规定时间内目标查找。(BFS)

    4:查找最近目标(BFS,Rescue,这个正确的解法是目标来查找起点。也就是说我们要有个思维。目标和起点是能互换的。另外。HDU的数据很弱。这个好题啊。这个题目值得讲讲。毒药血药问题。)

    。。。(我还是新手待填充)

    分析BFS:

    基础的BFS按照以上是能解决的。

    而BFS往往会有别的条件,比如某种技能(穿墙,走两步,行和列坐标变化。。。)种种技能。同时这技能往往会弄上数值代表能使用的次数之类。

    其实这些技能只是多了方向而已。多了种你能行走的方式。 当然。技能值越多往往是越好的(因为你有更多的选择,或者说因为有技能而有更快的方案,或者是不得不用技能的情况。比如前面有墙。你用穿墙术。)

    那好。我们的首要任务明确了。分析什么是时间什么是技能值。其实这个很简单。只要看输出。要求什么最小即可。(两者都最小的话,我还没遇到过。)

    什么最小什么就是时间除此之外,其实看看题目就能区分开来。

    除此之外让我们看清楚BFS的的搜索过程。它是搜索在这个点能到达的点集的点。也就是说时间和它的关系是每一步增加一下时间。那么。技能只是在控制方向的话。我们并不需要去考虑因为技能而变得不再是简单的BFS类型。(当然那个技能不是做出什么让时间加一减一的事情。也许它可以通过穿墙使得时间变短,但这并不违反简单的BFS)那我们可以放心地只是在方向上进行改造。

    NightMare:有一个数值是炸弹爆炸的数值 还有一个统计总时间。 我们要控制的量是总时间。所以这个是上述的时间。而炸弹爆炸其实应该抽象成一个技能。能够行走的技能。而亭子能够让技能恢复。

    捡骨头:(学长原创题)大意就是你有一项可以走两步并且时间耗费只用1的技能(其实就是不影响时间的方向)。并且你可以借此来穿一层墙。这很明显。技能是走两步(方向拓展,我们只要在搜索的时候扩展一下方向)。

    上述两类你会发现所谓技能只是让行走变得方便或者迟钝。总之就是方向上的控制(也许你会觉得前者感觉不像。但是你可以认为一开始你连走都不能走,所以爆炸了就果断continue。)。这两种都有个问题。也就是标记问题。同一个地方并不是走过就不能走的。一个很简单的例子。 你用技能走到了一个点。但是同样你可以不用技能走到这个点。前者没技能了。而后者有。 然而后续情况必须你有技能点。所以你不能用传统的标记手段了。你必须新NEW一个mark数组。然后去找最优的(也就是技能点最大的)情况。

    其实除了经典的技能问题。还有别的问题也是如此。

    只要抓住其根本。这些因素是影响方向的。而不是影响时间本身!就符合简单的BFS。

    Rescue:有直接影响时间的因素。

    你会发现。这个时候你这个点能相通的点集并不是时间最小的点。所以这并不符合简单的BFS。那么你就需要每次在放入点。拿出点的时候。要取时间最小的点。因为你可以到达的还是那样没变。然后你应该从时间最小的开始遍历。这个你就需要用到优先队列了。

    优先队列的使用:

     1    #include <queue>    
     2     struct Node
     3     {  
     4         int x;
     5         int y;  
     6         int time;  
     7         friend bool operator < (const Node &a,const Node &b)  
     8         {  
     9             return a.time>b.time; // > 的是对的 也就是返回小的。
    10         }  
    11     }now,next;  
    12      priority_queue <Persion>q;  
    13     
    优先队列的使用

    综上两种:分析一个问题。HDU-1180.诡异的楼梯

    楼梯会随着时间而变动方向。

    我们先考虑不变方向的楼梯。很明确。就是第一种情况。只是影响方向而已

    如果这个楼梯会变方向。并且你并不能原地暂停。这个问题始终还是第一种情况。(即使你再一个返回还是不能通过。并且根据奇偶剪枝的知识。你会发现不能通过的点始终不能通过。即使你走了再复杂的路线。)

    然而这个问题上我们可以等一秒再通行。这个原地暂停。

    导致了不是简单的BFS。因为简单的BFS是你这个点能相通的点集并不是时间最小的点(同时很正常的只能搜索一次),因为你的点集会发生变化。(在楼梯前的那些点)所以你必须要2次才能搜索完它通的点集。或者需要的时间更多。

    并且原地暂停这个并不适合加在方向上。因为无论是时间标记还是地点标记都不允许这类情况出现。即使加上去也太损耗效率。

    所以利用优化队列转化成简单的BFS。

    对楼梯处的方向处理。最难的地方就是原地了。怎么做到原地?

    我的思路是直接走过去。如果是不行情况的楼梯。那么时间+2.如果是可行情况的楼梯。那么时间+1.

    由于优先队列能帮忙调整。所以会符合。(其实即使是简单的BFS也能把普通队列改成优先队列来做。只是会耗费时间。)

    别人的思路是。楼梯也是一个可达方块。时间在上面损耗。假如是符合的。还要处理时间-1。

    其实观察我们对时间的处理。就能很简单发现这是第二类情况的问题了。尽管说原地暂停这个并不是十分明显。(其实考虑一下 原地暂停就是时间+1啊。)这样就能清楚明白了。

    最后:同样可以解决二种情况结合的问题。标记和优先队列并不会冲突。

       其实我是分析了在第一种情况中的一个特殊情况 也就是有技能值得情况。而普通梯子 和 空间传送器 之类的问题就是最最简单基础的BFS问题而已。   并且不用特殊标记时间,可以标记的是位置。

  • 相关阅读:
    LeetCode Count of Range Sum
    LeetCode 158. Read N Characters Given Read4 II
    LeetCode 157. Read N Characters Given Read4
    LeetCode 317. Shortest Distance from All Buildings
    LeetCode Smallest Rectangle Enclosing Black Pixels
    LeetCode 315. Count of Smaller Numbers After Self
    LeetCode 332. Reconstruct Itinerary
    LeetCode 310. Minimum Height Trees
    LeetCode 163. Missing Ranges
    LeetCode Verify Preorder Serialization of a Binary Tree
  • 原文地址:https://www.cnblogs.com/Milkor/p/4256330.html
Copyright © 2011-2022 走看看