看到一些“高深莫测”的词不要害怕~ 认真耐心看~ 会简单很多~
掌握还需多多练习
一、BFS和队列
上两篇广搜题解都在讲BFS如何运用队列的,不再赘述
二、八数码问题和状态图搜索
BFS搜索处理的对象不仅可以是一个数,还可以是一种“状态”。八数码问题是典型的状态图搜索问题。
1、八数码问题
也是一种简单的扩散过程,从初始状态出发。在八数码问题的搜索树中,存在重复的状态,八数码的重要问题:判重。
2、康托展开(一种判重方法)
每种状态对应一个数字。也是有顺序的,状态有9!种,从小到大。依次对应0,1,2……9!-1。原理:涉及到“第几大排列数”的问题。原理书上都有,来看一下康托展开判重的代码。
const int fact[10] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};//阶乘
// permutation 输入的一个全排列
//num 第几个全排列
int contor(const vector<int>& permutation) {
int num = 0;
int len = permutation.size();
for (int i = 0; i < len; ++i) {
int cnt = 0; // 在i之后,比i还小的有几个,即在未出现的元素里第几大
for (int j = i + 1; j < len; ++j)
if (permutation[i] > permutation[j]) ++cnt;
num += cnt * fact[len - i - 1];
}
return num + 1;
}
三、A*算法
A*算法,让盲目的BFS更智能一点。“BFS+贪心”
例如最短路径问题中引入曼哈顿距离(该点距离终点横纵坐标之和),就可以去除远点走近点。还有另外一种特殊的情况,障碍物的存在,即使最近但不能直接通过。(需要评估函数)
四、双向广搜
知道起点和终点,并且正向和逆向都可进行搜索
(练习)
五、DFS
1、递归
一条路走到无路可走,再返回到有路可走的最近结点。
2、回溯和剪枝
有时一些路径没必要走到底(因为已经知道不符合要求),“看到不对头就撤退”,意思是中途停止扩展就返回,就是回溯。在回溯中用于减少子结点扩展的函数就是剪枝函数。典型八皇后。(练习)
3、迭代加深搜索(IDDFS)
一种结合BFS和DFS的方法。典型埃及分数。先确定深度,广搜索,未找到答案,在增加深度。
4、IDA*
IDA是迭代加深搜索(IDDFS)的优化,预测当前dfs状态,不在深入,及时止损。简单来讲,IDA用到了估价函数进行剪枝。以下这个例题来更好的理解这个操作~
poj3134该题难点在于,每一步搜索,新值增长极快。DFS和BFS数据可能会出现溢出。用迭代加深搜索(IDDFS),再用估价函数进行剪枝,就可以高效完成。
1.IDDFS:指定递归深度,每次DFS不超过这个深度就好
2.估价函数:如果当前的值用最快的方式(连续×2,倍增)都不能到达停止用这个值继续DFS,
都是一些书本上学来的,其实都很浅(慢慢学也会有成就感)