3.8 搜索题的一些调试技巧 3.9 小结

本文介绍了搜索题目的调试技巧,包括使用DFS时如何逐步添加和调试剪枝,以及BFS的调试方法。同时,文章总结了搜索算法,如DFS、BFS和迭代加深搜索的应用,并强调了搜索优化的重要性,如剪枝、确定搜索顺序和降低计算代价。
摘要由CSDN通过智能技术生成

3.8 搜索题的一些调试技巧

如果决定用 DFS 做一道题,那么:
 如果能套用模板或经典的 DFS 模型,就直接套用。
 如果不能套用,就先写爆搜,并命名为#0 版本。
 对于每一个版本,调试正确之后,再进行剪枝,并且每次只加一个剪枝,调试正确后再继续。
 每次加剪枝都应该开一个新的版本,不能直接修改原版本。

    如果时间来不及了,就按照从强到弱或从好写到难写的顺序来加剪枝。
 在动态查错之前应该进行一次静态查错。
 调试时,如果出现 RE(运行时错误)或死循环,就在出错的状态处停止,并检查其所有的祖先      状态(显然这需要记下每次的决策),看看这些决策是否合法。

 如果程序正常结束,但结果错误,应该从以下三个角度入手:
    1. 明明有解,输出无解:可以把正解的各个决策一步一步代入,看看程序里面是在哪一步出了        问题(明明合法的决策它木有作出),从而方便检查;
    2. 输出不合法的解:可以把形成这个不合法解的决策一步一步代入,看看是哪一步出了问题;
    3. 输出合法但非最优的解:必然是某些最优性剪枝错误或者最优性判断出了问题,可以直接到        这些地方去检查,实在不行也可以把最优解代入检查。
 有时也可以用分段检查的方法,即把代码中的各个过程或者片段截取下来,将几组小的输入代入,看
看执行之后,所有在该片段里改变了值的全局变量是否正确,进而发现这里的错误。
 千万不要一下子输出全部的状态!这样不仅不容易查出结果,还把容易把自己绕晕。
事实上,只有在状态总数不太多,且相对关系明了、顺序整齐的时候(比如一般的 DP 等),可以一下子输出全部状态来检查,否则就不能这么做。

对于 BFS,其实它比 DFS 容易调试,因为所有的状态都储存在队列里。因此,可以在状态结点中记下每个
点的前趋,然后,哪里出了问题,就直接把它的前趋状态全部输出。
另外,BFS 一般没有“剪枝”这一说(除了判重),且决策过程一般是比较整齐的,因此更容易调试。

3.9 小结

搜索,就要用搜索算法来产生所有可能的答案,并从中筛选出正确的答案。
搜索法常用于求可行解或可行解的个数。在竞赛中,搜索法还是“救命稻草”——大多数问题都可以使用
搜索来谋取部分分数。
搜索的方式有很多种,常见的有:枚举搜索、深度优先搜索、广度优先搜索、迭代加深搜索。
解搜索题时要从以下几方面入手:确定状态、确定结点扩展方式、选用合适的搜索方式、优化。
1. 深度优先搜索和广度优先搜索
将搜索时产生的状态组成一棵树,就成了解答树。深度优先搜索和广度优先搜索的区别在于解答树的遍历
方式。下图是一棵解答树:

深度优先搜索用逐步加层的方法搜索并且适当时回溯,遍历过程如下图所示:

 广度优先搜索得名于它的实现方式:每次都先将搜索树某一层的所有结点全部访问完毕后再访问下一层, 再利用先前的那颗搜索树,广度优先搜索以如下顺序遍历:

 首先访问根结点,而后是搜索树第一层的所有结点,之后第二层、第三层……以此类推。
此外,在使用广度优先搜索时,应小心处理空间问题。
下面是两种搜索算法的比较:

DFS BFS
优势1. 比较适合回溯类搜索
2. 参数传递、状态修改和恢复都比较方便
3. 自顶向下地处理问题
4. 记忆化搜索容易实现
5. 能很快到达解答树的底端
1. 解决“最少步数”、“深度最小”问题
2. 问题的解靠近解答树的根结点
3. 启发式搜索在BFS中更容易实现
4. 能立刻停止搜索
缺点1. 使用递归算法容易导致栈溢出
2. 有时不容易输出方案
3. 不易立即结束搜索
1. 空间一般比DFS大
2. 状态重复的排除有时耗时多

2. 迭代加深搜索
广度优先搜索可以用迭代加深搜索代替。迭代加深搜索实质是限定下界的深度优先搜索,即首先允许深度优先搜索搜索 k 层搜索树,若没有发现可行解,再将 k+1 代入后再进行一次以上步骤,直到搜索到可行解。这个“模仿广度优先搜索”搜索法比起广搜是牺牲了时间,但节约了空间。
在需要做 BFS,但没有足够的空间,时间却很充裕的情况下,可以考虑迭代加深搜索。
迭代加深搜索的时间不会超过等效 BFS 占用时间的两倍,当数据规模增大时,二者的差距还会逐渐减小,而迭代加深搜索的空间占用和 DFS 一样小。
3. 搜索的优化
没有经过优化的搜索叫“爆搜”或“裸搜”。爆搜能承受的规模不大,原因有二:一是搜索时产生了无用的结点,二是重复计算。
优化时从以下几方面入手:确定更合适的搜索顺序、剪枝(可行性剪枝、最优化剪枝)、降低考察和扩展结点的代价,必要时可采用高级的搜索方法,或使用状态压缩。
此外,写搜索程序时应该先从朴素算法入手,逐步优化,以降低编程复杂度、减少不必要的失误。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值