|
使用Java小程序的交互式专栏 亚历克斯·博戈莫尼
|
迷宫
2003年10月
很久以前,在爱荷华州的一家木匠店,我为我的第一台电脑买了一张未完工的桌子,这是IBM当地办事处的一笔赠款。我对35美元的价格感到惊讶。“撇开材料成本不谈,单是人工成本就应该比这高。”木匠自豪地回答道,“如果你知道如何切割和组装工件,那就不会了。”我总是记得这一集,当时我试图解决的一个问题有一个我一直没有找到的简单解决方案。
有很长一段时间,我想写一个电脑程序来画迷宫。我甚至也尝试了几次。但没有一个是令人满意或满意的。当它最终问世时,已经有了创建和解决迷宫的成熟技术,这可能是每个计算机科学专业本科生都知道的。事实上,网络上充斥着学生们在互联网上发布家庭作业的有据可查的例子。但当然。。。图形和迷宫是一回事,至少在某种意义上是一样的。需要注意的是,迷宫的表面复杂性不应该用肉眼来判断,而应该用肉眼来判断。可以称之为希尔伯特迷宫。(要查看该示例的所有精彩之处,请选中“迷宫”并继续单击下面的小程序。)
作为一个图表,希尔伯特的迷宫是微不足道的。只有两个顶点 图表由单个连接边缘,后者是著名的平面填充曲线的正则近似。类似的观察结果适用于皮亚诺迷宫,尽管有272其中之一。奇怪的是,许多历史迷宫[杜德尼,加德纳,劳斯·鲍尔]都是这样的。这条小路蜿蜒曲折,从入口到出口的路程很长,但不用担心——在树篱中是不会迷路的。(然而,关于皮亚诺和希尔伯特的迷宫,人们可能会考虑限制迷宫的特性。路径仍然在那里,但通道太窄,挤不过去。如果可以的话,这将是一段漫长而可怕的旅程。这一情况值得芝诺注意。)
在复杂性上仅次于琐碎的迷宫是由树。树是从每个顶点到任何其他顶点都有一条路径的图。任何有联系的图形具有生成树也就是说,一棵树子图具有完全相同的顶点,但只有一些边。
有几种算法可以从给定的图中提取生成树。下面的小程序实现了其中两个。两者都有Prim的和Kruskal的算法于1956年出版。两者都是迭代的,并举例说明了贪婪策略,但方式不同。Prim的算法从一个顶点开始生长一棵树,这是最简单的树。在每次迭代时,它都会向现有的树中添加一个分支——一个顶点和一条边,将顶点连接到树上,这样生成的图形仍然是一棵树。为此,顶点不是从树上的顶点集中选择的,而是通过至少一条边直接连接到树上的。自然,每次迭代都会更新候选顶点集[列维京第305-309页]。
克鲁斯卡尔算法从所有顶点集和空边集开始。在每次迭代中,都会向集合中添加一条边。此过程中的唯一限制是添加边不应创建电路,一个路径以相同的顶点开始和结束。(设计了简单的结构和算法来加速验证,参见[列维京第314-317页)
事实上,情况比刚才描述的要复杂一些。两种算法都适用于权图,其中为每条边指定了权重。算法包括贪婪的在每次迭代中,他们从可用集中选择一条权重最小的边。生成的树称为最小生成树。(如果没有权重,产生的迷宫就没有吸引力。小程序几乎是随机分配权重的。)归纳法的简单证明表明算法确实有效。
解决迷宫的标准方法之一是深度优先搜索[列维京技术:从一个节点沿着一条路径走,直到到达一个死胡同。退回路径,直到第一次有机会检查另一个节点。从那里继续。重复该过程,直到访问完所有节点。
下面的小程序有四个选项卡-定义网格、定义形状、创建迷宫和求解迷宫。起点是尺寸范围为2到50的矩形网格。网格的形状可以通过删除一些顶点、将一些删除的顶点放回原处以及选择开始(蓝色)和结束(红色)顶点来更改。无论如何,必须单击顶点。如前所述,要创建迷宫,您可以选择Prim和Kruskal的算法。您可以通过单击“一步一步”按钮来观察它们的工作,或者使用“一步”键一次执行一步。您还可以观看迷宫的求解或一次执行一步(深度优先算法)。
英语单词“maze”,只有在14第个世纪与道路网络联系在一起[施瓦茨曼]与更长的形式“amaze”有关。古时候有这样的说法[杜德尼惊愕意味着“陷入沉思”,这可能会在迷宫中自然发生一次。如今,当我们面临困境时,“迷宫”这个词仍然会浮现在我们的脑海中。“惊奇”一词现在有了不同的含义。参考这个词后来的、现在的习惯用法,一旦“你知道怎么做”,事情就变得很简单了,这当然令人惊讶
工具书类
- H.E.Dudeney,数学中的乐趣1970年,多佛
- M.加德纳,第二本科学美国人的数学困惑与转移书芝加哥大学出版社,1987年
- A.莱维汀,算法的设计与分析,Addison Wesley,2003年
- W.W.Rouse Ball和H.S.M.Coxeter,数学娱乐和论文1987年,多佛
- S.Schwartzman,数学词汇,1994年5月
|联系人|
|首页|
|目录|
|几何图形|
版权所有©1996-2018亚历山大·博戈莫尼
Prim和Kruskal的算法确实有效。
证明的基础首先是最小生成树的存在性。任何连通图都有生成树的子图。事实上,如果给定的连通图本身不是树,那么它就有一个回路。从图中删除此回路中的任何边都会使其与相同的顶点相连,但边更少。如果在这个阶段,剩下的图是一棵树,我们可以停止。否则,边缘去除过程将继续。但是,由于边的数量是有限的,它不可能永远持续下去。如果|S|表示集合S中的元素数,则当|V|=|E|+1,因为,正如很容易看到的那样,这个属性是树的特征:对于连通图|V|=|E|+1,移除任何边都会使其断开连接。
对于加权图,生成树的数量,无论多大,都是有限的。因此,在给定图的所有生成树中,存在可能具有最小权重的树。
现在让我们来看一下这两个算法实现了承诺的证明,即每个算法都会导致给定图的最小生成树。将给定图的顶点集表示为V,将其边集表示为E我和E我表示在i上聚集的顶点集和边集第个任一算法的步骤。我们给他们打电话<V我,E我> 可接受的如果它可以包含在最小生成树中。我们必须证明,在每一步,算法都会产生一个可接受的对。什么时候?|E类n个|+1=|V|,图一定是一棵树,它包含给定图的所有顶点,因此,它是它的生成树。
由于这两个算法的证明非常相似,我将把它们安排在两列中。证据由归纳.
普林演算法 | | 克鲁斯卡尔算法 |
在算法的每一步上,我们都有一组由边连接的顶点,这样它们形成的图就是一棵树。 | |
在算法的每一步,我们都有一组边,这样它们形成的图形是无回路的。 |
让V0由单个顶点(起点)和E组成0为空。 | |
让V(V)0=V和E0为空。 |
由于存在最小生成树,<V0,E0>是可接受的对。 | |
由于存在最小生成树,<V,E0>是可以接受的一对。 |
假设这对<Vk个,Ek个>在k上生成第个步骤可以接受。为了完成证明,我们将展示这对<Vk+1(千分之一),Ek+1(千分之一)>也是可以接受的。 | |
假设这对<V、Ek个>在k上生成第个步骤可以接受。为了完成证明,我们将展示这对<V、Ek+1(千分之一)>也是可以接受的。 |
相反,假设<Vk+1(千分之一),Ek+1(千分之一)>不可接受。 | |
相反,假设<V、Ek+1(千分之一)>不可接受。 |
假设存在最小生成树<V,F>带Ek个F的子集。假设ek+1(千分之一)是Prim算法在(k+1)上选择的边标准步骤。相邻ek+1(千分之一)到F一定会产生一个电路。 | |
假设存在最小生成树<V,F>带Ek个F的子集。假设ek+1(千分之一)是Kruskal算法在(k+1)上选择的边标准步骤。相邻ek+1(千分之一)到F一定会产生一个电路。 |
这意味着存在另一条边e,其权重至少为ek+1(千分之一)将其从F中删除将留下一棵树<V,F-{e}+{ek+1(千分之一)}>.后者的权重不能超过最小生成树的权重<V,F>因此,它也是最小生成树,但与我们的假设相矛盾的是,它的边集包含Ek+1(千分之一). | |
这意味着存在另一条边e,其权重至少为ek+1(千分之一)将其从F中删除将留下一棵树<V,F-{e}+{ek+1(千分之一)}>.后者的权重不能超过最小生成树的权重<V,F>因此,它也是最小生成树,但与我们的假设相矛盾的是,它的边集包含Ek+1(千分之一). |
|联系人|
|首页|
|目录|
|几何图形|
版权所有©1996-2018亚历山大·博戈莫尼