连连看,转载自:薛笛

[align=center][img]http://dl.iteye.com/upload/attachment/0069/4864/85302039-c84a-3258-a456-987c3804e247.png[/img]
图1 广度优先路径搜索[/align]
书中给出的解法利用了广度优先搜索算法,本质上是一种建立搜索树然后剪枝的策略。具体过程如图 1所示:目标是要找到从左上角的圆形图形(设为图形1)到右下角的圆形图形(设为图形2)之间不超过3个弯的最短路径。首先在图形1所在位置向四个方向进行直线查找,如果在某一方向上找到图形2则结束。否则,记录下所有这四个方向上的空白格子,并在每一个空白格子的其他3个方向上进行直线搜索。如果仍未找到图形2则再次记录下查找过程中沿途记录下来的空白格子(要去掉已经走过的空白格子),仍然在3个方向上进行搜索。若找到则返回结果,若还未找到则说明两个图形之间不存在不超过3个弯的路径。这个算法很直观,就是在有限的转弯次数内不断构建出更大的路径网络,看看能否“覆盖”到被连接的图形,但似乎还可以进一步提高效率,下面就给出我的一些想法。
[b]相同图形对之间的最短路径查找算法[/b]
以图2为例,我们的目标是找到图形1和图形2之间的最短路径,我们从图形1出发进行查找动作。由于题目要求最短路径不能超过3个弯,并且我们知道:“直线路径长度≤带有一个弯的路径长度≤带有两个弯的路径长度”,所以下面我们将分三种情况进行讨论。
为了加速程序运行,这里还引入了图3所示的两个辅助数据结构,其中每一个方块中都带有一个二进制位,用来表示在该位置上的格子是否是空格子,0代表是空格子,1代表有图形存在。虽然左右两组数据结构的内容是一样的,但是其组织方式有所不同:左边的二进制位是按列组织的,即一列的二进制位保存在一个int或者long型的变量中,多出来的位用0填满;右边的结构是按行组织的,其他与左边结构类似。这两个结构具体的功能后面用到的时候会详细介绍。
[align=center][img]http://dl.iteye.com/upload/attachment/0069/4866/3824e07d-901e-31ea-9e7b-ad2fee87b17d.png[/img]
图2 改进的路径查找方法示意图[/align]
首先,应该判断是否存在图形1到图形2之间的直线路径。这一点我们可以通过他们的位置信息直接得到,例如图形1的位置是[2,2],图形2的位置是[4,5],很显然二者不会在一条直线上,所以直接跳过这一步。但如果二者在一条直线上的话,还需要判断他们之间是否有障碍物存在。例如,如果图形2在[5,2]的话,我们可以断定二者在同一直线上,但我们还需要检查在二者的直线路径上是否还有其他图形存在。因为两个图形同在第二列上,于是我们取图3左边结构的第二列变量C2(这里假设是一个8位的Byte变量),然后做val=C2&00110000,注意其中的两个1是用来测试在图2的第二列上是否有非空的格子。如果val=0则说明两个图形间存在直线路径,否则说明二者之间不存在直线路径。这一过程的时间复杂度为O(1)。
第二步,查找二者之间是否存在转弯一次的路径。从图中我们可以清楚地看到,这样的路径只有两条,他们组成了一个矩形,图3中蓝色的矩形就是两条路径的组合而成。我们可以用上面的方法分别来测试这两条路径上是否有障碍存在,如果没有障碍则作为最短路径返回,否则就要进行第三步。这一步的时间复杂度也是O(1)。
[align=center][img]http://dl.iteye.com/upload/attachment/0069/4868/bbcb8fe8-7fbe-3a3f-b9ee-8aac496412da.png[/img]
图3 辅助数据结构[/align]
第三步,查找两个图形间是否存在转弯三次的路径。首先我们用书中给出的方法在蓝色矩形内部进行路径查找,但是限制只在“向右”和“向下”两个方向上进行操作。如果没找到所需路径,则需要再次扩大搜索范围。如图2所示,在这一步我们需要把搜索方向在“向上”和“向左”两个方向上扩展,所获得的路径分别用红色框和粉色框表示,这个动作类似于把蓝色框向上和向左拉伸。对于获得的路径上的3条线段,我们只需用第一步所提到的方法来查找是否存在障碍即可,若3条线段都没有障碍则返回该路径作为最短路径;否则继续向两个方向扩展搜索范围直到搜索范围到达格子的边界,若仍未找到则认为两个图形间没有符合条件的最短路径。可以看出,由于不需要对同时对4个方向上所有空闲格子进行广度优先搜索操作,第三步的时间复杂度应该低于书中所给出的算法。
[b]扩展问题的研究和修改意见[/b]
[i]扩展问题1的研究[/i]
扩展问题1说的是(1)是否可以通过维护任意两个格子之间的最短路径来实现快速搜索。(2)在每次消去两个格子之后,自然更新要更新需要维护的数据,这样的思路有哪些优缺点,如何实现。
粗略想来,由于用户每次只能消除一对图形,即只会用到一个最短路径,但由于实现并不知道用户会选择哪一对图形,所以需要事先计算出所有可能的最短路径并保存起来。此外,采用这种方法的话似乎每次用户消去一对相同图像之后都需要重新计算出当前所有可能被连接的相同图形之间最短路径,这是因为当某些图像被消去之后可能会产生很多新路径,而我们又不能确定这些空出来的格子到底能够影响哪些路径,所以就只好都重新计算一遍。其缺点很明显就是每次消去图形动作之后重新计算所有可能的最短路径所需要消耗的时间;而该方法的优点则是可以很快地判断两个相同图形之间是否存在满足条件的最短路径。
如果用户很厉害,每次都能选中可以消除的图形对,那么用这种方法浪费的时间就会相当可观,毕竟用户未选中的其他可以连接的图形对之间的最短路径都被浪费掉了;而如果用户很差劲,每轮选择的次数都远远大于当前可能的连接数量时,该方法就会比书中正文提到的方法高效。但这种情况是比较少的,因为在整个游戏中用户主要是会用眼睛“找”而不是频繁的用鼠标去“试”。所以总的来看,维护所有最短路径的方法的效率相对比较低。
[i]修改意见[/i]
(一)书中给出了这个游戏几个关键点是:怎样求出相同图像之间的最短路径(路径的转弯数最少,经过的格子数最少,书中规定路径不能超过两个弯)。然而让人迷惑的是,在“分析与解答”的开始部分数中提到了用自动机模型来描述游戏设计,当时我想难道本章会有像字符串匹配问题那样利用自动机进行问题求解的方法吗?但是在后面却没有看到任何应用自动机理论来解决问题或进行算法优化的内容。虽然游戏设计时常常会用自动机来描述游戏的状态转换,但书中本章的主旨是寻找相同图像之间不超过3个弯的最短路径,并没有将自动机的能力应用到算法中以加速寻径过程;退一步说,如果只是讲游戏设计的通常做法的话,那又和本章的内容有什么联系?所以还是建议去掉这一段以免造成误解。
(二)关于扩展问题(1)的题干我想应该不是“任意两个格子”之间的最短路径,因为维护这样的路径是没有意义的。而应该是“任意两个带有相同图像的格子”之间的最短路径才对。

转载地址:[url]http://blog.csdn.net/kabini/article/details/2598524[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值