搜索

暴搜,永远滴神!我宣誓:我自愿加入暴搜流派,保证每道题目能用暴搜,坚决不用其他算法,暴力搜,剪枝完,TLE就换题,从A题搜到最后一题,系统栈空间不够?自己手动模拟栈也要暴力,暴力就是神!!!

暴力的题目一般很容易就能够看出来, 数据的范围上基本上就是在10 - 20 的范围内,加上剪枝的话还能更大。

先bfs。

首先,bfs最基本的应用就是 flood fill 模型,这个是最简单的模型,我们可以枚举每个点是否被遍历来扩展其连通块,这里要求的连通块的树形有很多,比如:面积周长,等等等等。。 在开始的时候最好将方向数组处理好 。

第二个就是最短路问题,这个应该是bfs最常见的应用了,其中最简单的标准是求权值等价的图的最短路。我们先来验证下其正确性,我们需要验证其两个性质,单调性和两段性,首先两段性,我们的操作的顺序是:把搜索顺序想象成一棵树,我们在访问完所有的第i层的节点,我们才会开始访问第i + 1层的节点。由于两段性和所有的权值是1得知,第i + 1 层开始遍历到之前没有遍历到的节点到起点的距离一定大于前边遍历到的点到起点的距离,得证其队列的距离具有单调性。证得了这两个性质,我们可以再运用反证法:假设队头在第一次出队的时候不是最小值,那么会存在有一条后边的点组成的点到该点的路线距离更加小,而队列的点的值是自始至终是递增的,并且所有的权值是正数,所以不存在这样的路线。因为所有的权值是一样的,后边的点的值只能是越来越大,每一次进行树的深度加深的时候,后边的点的距离只能是大于前边点的距离,只要是入队了,最小值就已经确定了,这就相当于一个特殊的堆优化版的 dijkstra 算法,bfs最重要的一点就是所有的状态按照入队的先后顺序具有步数单调性,已经出队的元素相当于已经在队列中固定了一个虚拟的位置,如果不能保证,那么只能将点进行多次更新才能找到最优的解。

还有更加一般的情况,权值是不固定的,但是权值都是正数,那么我们该怎样呢,一种做法是遍历所有的路径,允许一个状态多次被更新,对应到最短路算法就是SPFA,这里的队列最初出列的点并不一定是其最小值,所以可以处理负权边。另外一种就是强行让队列中的元素单调,需要用到优先队列,这里权值只能为正,因为这个算法成立的条件中用到了权值必须为正的条件,对应到最短路算法是堆优化版的dijkstra算法。

如果是权值只能是0,1,那么可以用双端队列deque,更新时遇到权值为0 的就放到队首,遇到权值为1 的就放到队尾。这样队列中保证了其单调性,并且后边的点不可能更新到前边的点,最多也就是相等。

第三个是双向广搜,就是在知道问题的答案的时候,我们可以从答案开始向起点搜,对应着前边起点也向答案搜,这样可以大幅减少搜索的空间,一般可以将 kN 的复杂度降低到2 * kN/2,但是需要知道目标状态。注意:这里每次对两个队列进行扩展的时候,一定是要扩展一整层,不能只扩展某个点的对应的层数。debug一整天的痛苦经历你是不会忘的对吧~~

最后就是A*算法了,这个算法应该是我难理解的一个算法之一了。维护的是一个优先队列,算法的引入是预先估计目前状态到目标状态的一个权值,所以需要先想一个启发函数,要求预估的权值不能大于真实权值,只有这样才能保证结果的正确性。

证明: 首先如果s不是最优解,那么当s扩展到终点的真实距离一定大于最优解上的点到终点的距离,又因为我们这里模拟的估计距离不大于真实距离,那么s肯定不会从队列中被弹出来,也就是其到终点的距离不会被选择。

dfs :

dfs写起来简单,但是如果剪枝不好的话很容易爆栈和TLE,所以剪枝是一门艺术,学好剪枝需要强大的直觉和经验,这都是需要刷题量来支撑的。

首先的剪枝是搜索顺序,dfs的搜索顺序是很重要的: 这在很大程度上决定了树的规模和大小,配合上剪程序就会非常高效,就算没有剪枝高效的搜索顺序也可以大幅优化搜索的效率,在搜索树中所有到的叶子节点的路径都可以当成是枚举一种方案,其中有些路径所经过某些的节点是相同的, 优化搜索顺序主要优化的是我们可以将路径某些相同的点合并,然后在搜索中就没必要重复搜索这些相同的点,比如:这里有两种方案12341235其中如果我们先遍历123然后在3处可以分出两个点45,但是还有一种枚举方案是先枚举的45那么 123 就会被遍历两遍,搜索效率会下降,一般来说,一般是先搜索其造成节点数较少的点 ,然后在进行节点数较高的点。

其次就是避免重复的计算数据相同但是排列不同的方案,解决这点可以人为的给其定一个顺序。每次传入一个参数,可以使枚举的方案中的数据下标递增,这样就可以避免枚举相同的方案。

还有就是,最优化剪枝,这个一般都可以想到。

最难的就是可行性剪枝,需要具体问题具体分析,分析出一个上下界。

以后还要补充!

如果是维护在路径上的属性的时候,最好还是用dfs,当然看下所要传递的属性是什么,实际上bfs能够维护的东西挺少的,要不维护起来就特别麻烦。太浪费空间~~~dfs每次都遍历都是一条完整的路径,比较好维护~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值