题目链接
1 | /* |
题目分析
在做一道算法题目的时候,我认为真正地搞懂题目意思是非常重要的,题目搞不懂很可能会出现漏解的情况。我觉得从样例输入和输出出发,然后往题目中带,是比较好的理解方式。这道题目结合下图的理解如下:这个图我根据样例走了一遍,为防止混乱,先使用红色,当节点重复了再用蓝色,然后再用绿色,最终走到终点。

首先看样例输入的第一行,一个起点坐标(3,1)代表第三行第一列,一个离开起点时的位置N代表离开起点时朝向上,一个终点坐标(3,3)代表第三行第三列。一开始的时候我是有点疑问的:为什么上图的最下面有两个点表示起点和终点和样例中的不太一样啊,可后来想了想,样例输出可以有很多的,题目中的图只代表了一种情况,所以不用管多余的点。
然后看每一个坐标,都有进入坐标的方向,即NEWS,分表表示上、右、左、下,LFR分别表示进入该点可以向左、直走、向右走。结合样例比如1 1 WL NR*,对应图中的(1,1)坐标点,表示当进入(1,1)时的方向,如果是W,即向左的话,那么此时你只能左转;如果进入(1,1)朝向向上的话,此时只能右转,输入*代表此节点的输入结束,接着读取下一行,然后输入0代表整个输入结束。
研究对象
说是研究对象可能有点过了,这里我指的是在算法解决问题的过程中所定义的几个重要的变量,下面针对我认为很重要的变量解释一波。
1 | /* |
研究方法
对用来解决问题的函数方法先说明一下。
read_case();该方法是将所有的输入转换到has_edge数组中,表示此状态下节点所允许的转向。结合上图的BFS树理解也就是在该节点状态下有几个分支可以走。
dir_id();将NESW四个方向转换为0~3整数,方便在数组中当下标使用。
turn_id();将FLR三个转向转换为0~2整数,方便在数组中当下标使用。
walk();这个函数极为巧妙,用来获取转向后的下一个状态。根据FLR三种不同的转向,如果转向为L,即向左转,那么就顺时针加三,比如此时朝向为S,转向为L,那么在现实中我们很容易想到就是E,但是利用代码的话就是(dir+3)%4,这里为什么要用加?这是因为用加的话取余就可以再次从头开始循环NESW,但是逻辑上应该是逆时针减一的;如果转向为R,即向右转,那么就顺时针加一;如果转向为F,那么dir方向不变。
可以画一下图,一下子就理解了,见下图。

solve();利用BFS方法模拟走路,分别查看FLR三个转向能否走,也就是层次遍历的核心了。然后每走一步就在上面定义的数组中更新一下状态,并把当前满足条件的分支加入到队列中。思路见下图。

最终可得到类似下图的BFS层次树

代码实现
下面就将详细的解题思路注释在代码中,有时候看代码比看文字理解起来更容易。
1 |
|
运行结果如下:

第二次代码实现
1 |
|