2018.2.5主要讲了搜索
搜索
最基本操作bfs和dfs。这两种手段在不同的问题中能有不同的效果。
如果有这样一棵搜索树: dfs是从根结点开始每一次都随便选一条路,走到叶节点再返回;二bfs是从根节点开始一层一层向下搜索。如果每一层都是无限的,那么需要用dfs,如果没有明确的叶节点,那么就用bfs。
剪枝
剪枝就是这样:
搜到一个结点
把子树全部切掉。剪枝一般有这样的方法:位运算(状态压缩)、改变搜索顺序、记忆化。
虫食算
题目地址:luogu虫食算
mayan游戏
题目地址:luogu mayan游戏
双向广搜
其实就是用两个队列建立两边的bfs。这里有个技巧,假设tag表示一个队列,那么1-tag就是另一个队列;比如tag是0号队列,1-tag就是1号队列。双向广搜可以需要hash表来进行优化(可以用map直接搞,但是需要O2优化。。。)
八数码
题目地址:这里写链接内容
启发式搜索
算法和算法。核心可以用一个式子写出来,这个表示已经走过的路,表示估计的最乐观的情况下还要走的路。
算法的充分条件是:
- 搜索树上存在着从起始点到终结点的最优路径
- 问题是有限的
- 所有节点的子节点的搜索代价值>0
-
h(n)预期代价<=实际代价(这一步体现了乐观性)
如果不满足上述条件,有可能弱化为BFS。
总结
今天讲的东西总的来说以前都学过。那些题目我还再刷一刷。还有今天上午的考试,还值得好好反思。总得来说还是缺少一个优化算法的总的套路。第一题的dp总的来说我是一个的暴力dp+剪枝,还是tle掉了。这道题目给的经验是dp的实现方式除了直接构造的算法(二分啊什么的),还可以通过一个式子推导,比如第一题,时间复杂度是,经过一番推导就是第二题和第三题我们什么好思路,都是暴力+剪枝。第二题的正解是容斥原理。把三个全排列想成三个集合,那么三个都相同的部分就是三个集合的交集。那就是容斥原理了。第三题采用两头搜索的bfs,就是两个队列,如果tar表示当前队列,那么1-tar就是另一条队列,这是一个小技巧。