由种子填充法谈两种基本搜索的实现

来源:互联网 发布:独立开发者知乎 编辑:程序博客网 时间:2024/05/11 13:34

         所谓种子填充法,就是常见的基本算法floodfill的中文名字。就像一滴墨水浸到宣纸之上,渐渐扩散。使用两种基本搜索——DFSBFS可以实现这种算法。下面我通过数据结构的层面来介绍一下DFSBFS的实现。

         首先来介绍“树”。计算机中的树和现实生活中的树相反——它的跟在上面,叶子在下面。相连的连个节点互为父子,同一高度的节点互为兄弟。如图:

 


         比如说:2,3,4节点互为兄弟;5,6节点是2节点的儿子;7节点是10,11节点的父亲。

         我们可以把DFSBFS分别看作在这棵树上的遍历(什么是遍历请自行解决)。那么DFS所经过的路径和BFS所经过的路径就如下图所示:


 

         当然我们可以把这两个过程分别在“堆栈”和“队列”中实现。什么叫“堆栈”和“队列”呢?

         “堆栈”的特点是FILOfirst in last out)。堆栈有一个栈顶(top),两种操作入栈(push)和出栈(pop)。我们将新的元素插入栈顶,也从栈顶弹出元素。这个过程就像DFS一样。而DFS的递归实现本身就是在“系统栈”中进行的。

         “队列”的特点是FIFO(first in first out)。队列有一个头(head)一个尾(tail)。在队尾插入新的元素(enqueue),在队头弹出元素(dequeue)。

         需要注意的是,我们在插入元素是要查看堆栈和队列是否会溢出,删除时要看是否为空。

 

         接下来,我们说说DFSBFS的实际应用和实现。就举种子填充法这个例子吧!这是一道IOI94的题目。我们看看一道IOI的题目是如何被我们解决的!

         在一个n*m的房子中有被墙分割的几个房间。对于每个单位空间我们用几个数字加和代表它周围墙的布局。我们用1代表西,2代表北,3代表东,4代表南。比如用 @表示出的(2,4)区域可以描述为1 + 4 + 8 = 13

 

     1   2   3   4   5   6   7

   #############################

 1 #   |   #   |   #   |   |   #

   #####---#####---#---#####---#  

 2 #   #   |   # @ #   #   #   #

   #---#####---#####---#####---#

 3 #   |   |   #   #   #   #   #  

   #---#########---#####---#---#

 4 #   #   |   |   |   |   #   #  

   #############################

 

         现在给你对于一个房子每个单位空间的描述,求出有多少个独立的房间和最大房间的面积。

 

 

         首先,我们尝试用DFS解决

         我们想到依次对每个单位空间进行floodfill,如果遇到了墙的阻碍,那么扩展就要停止。我们使用一个布尔数组来判断这个单位空间是否已经被访问。这个数组的作用我们叫做“判重”。扩展的过程就是递归地对周围四个方向允许被访问的区域再进行floodfill……


 

         这里的check是一个布尔函数,如何设计请自行分析。

         同样,用BFS也可以实现这个算法。我的习惯是使用一个记录类型的数组来实现队列。套用BFS的框架即可:

 

 

         这样,就把大体的框架展现出来了。当然,如果想解决这的题目也需要进行必要的完善,希望能自行解决这道题目!另外,题目的完整版还有另外两问,感兴趣的同学可以到以下链接查看:

http://www.nocow.cn/index.php/Translate:USACO/castle

         题目的提交可以直接在USACO中进行!

原创粉丝点击