数据结构A题

(1) 实现扫雷游戏程序

一、 核心算法的设计思路和实现要点

首先明确扫雷的规则,每次点击逐层打开不与地雷相邻的格子,若点击的格子下为地雷则游戏失败,当所有没隐藏地雷的方格均被打开(即所有没打开的方格后都有地雷),则游戏结束, 用户获胜。采用的核心算法为Deep First Search算法,用矩阵来模拟局面的变化,针对每次点击,若点击有效则按扫雷的规则想八个方向进行搜索,同时标记已被揭开的区域,为了算法优化,已被揭开的区域不会重复搜索并且标记为无效点击区域,设置计数器标记所有已经被搜索过的格子,当计数器数+雷数=n*m时,用户获胜,若在搜索过程中点击格子为地雷时,则用户失败

二、 算法时间、空间复杂度的估算

由于每次被揭开的区域在之后的点击中不做重复搜索(已经剪枝),故时间复杂度为\(O(n*m)\)

由于数组用于每次记录扫雷界面的局势,故空间复杂度为\(O(n*m)\)

三、 完成过程中遇到的问题,排除问题的主要过程、使用的方法和技巧

(1)DFS过程中出现死循环,要善用断点调试查找bug

(2)要注意审题,题目要求如果用户点击的方格是已被打开的方格,则点击无效,忽略该点击,并且只对用户每个有效点击所输出的信息用一个空行间隔,处理无效点击的关键就在于每次被揭开的区域在之后的点击中不做重复搜索,直接进入下一次点击或其他方向的搜素

四、 所用方法的特别、新颖或创新之处

在判断用户胜利时,不用对局势再进行搜索,而是使用计数器,置初值为k(地雷数),每次搜索到之前未被揭开的区域时加一,直到等于n*m时用户胜利。

(2) 智能扫雷算法设计与实现

一、 核心算法的设计思路和实现要点

首先分析题目,要求封装一个函数,在每次点击过后,根据当前的局势及扫雷的最优策略判断,自动给出下一次要点击的位置。我的算法为混合策略算法,即以下三种算法的最优合并

简单策略

(1)我们将所有的格子分为三类,一定是雷,不一定是雷,一定不是雷

(2)检查每个翻开的格子,若数字等于没被翻开的格子数,则没被翻开的全是雷,这样就能最大可能保证不输

(3)若周围雷的个数等于周围标记为雷的个数,那么没翻开的格子全都不是雷,那么我们优先点击这些一定不是雷的格子

(4)当一定不是雷的格子不存在,这是就需要我们使用以下两种策略

复杂策略

(1)首先我们明确,扫雷本质上解决的是n元一次线性方程组概率的可行解问题,显然在20*20的格子内,枚举的复杂度会是\(O(2^n)\),显然我们不能接受这个复杂度,为了补救,我们就需要引入局部的概念——把所有待判断的未知的格子划分为几个局部,而不是对所有格子一起判断。

(2)对每一个约束条件集合(局部),找出满足的解。首先提取出这个约束条件包含的所有的格子,需要找出的解就是指“这些格子是否为雷”的结果。然后使用回溯(backtracking)的做法方便获得所有满足的解。

  1. 中途剪枝:如果安排到一半,雷数量已经超了某个条件的总数那当然不行;而雷的数量太少,可能最后都没法满足条件也不行。
  2. 解的过滤:最后需要让所有约束条件满足的才是真正的解。

(3)找到所有解之中,不变的那个格子——对每个局部,把全部解求和之后算出是每一个格子是雷的概率,是0或者是1都可以实锤操作。

随机策略

当简单策略和复杂策略都无效时,我们考虑随机策略,即对n*m的数组扫一遍,统计那些不一定是雷的格子,存入随机数组,对下标进行随机

二、 算法时间、空间复杂度的估算

由于每次枚举每个点周围一定为雷的点和一定不为雷的点,故时间复杂度为\(O(n*m)\)

除了老师函数中已有的数组,我定义了地雷数组,用于记忆那些一定是雷的点,故空间复杂度为\(O(n*m)\)

三、 完成过程中遇到的问题,排除问题的主要过程、使用的方法和技巧

(1)随机化算法的部分发现可能会重复随机那些可能为雷的点,为了保证雷的概率,提高算法用桶算法来记录那些可能为雷的点

(2)复杂策略中n元一次线性方程组的解法复杂度过高,利用了分治的思想求局部的特征解

四、 所用方法的特别、新颖或创新之处

没有只用单个策略,而是使用了简单策略,复杂策略,随机策略的混合策略,具体实现方式在前文中已说明。

猜你喜欢

转载自www.cnblogs.com/fluxation/p/12424740.html