- 双向bfs适用于知道起点和终点的状态下使用,从起点和终点两个方向开始进行搜索,可以非常大的提高单个bfs的搜索效率
- 同样,实现也是通过队列的方式,可以设置两个队列,一个队列保存从起点开始搜索的状态,另一个队列用来保存从终点开始搜索的状态,如果某一个状态下出现相交的情况,那么就出现了答案
- 八数码难题
- 参考博客
以该题为例
状态表示可以采用康托展开:康托展开是一个全排列到一个自然数的双射,常用于构建哈希表时的空间压缩。 康托展开的实质是计算当前排列在所有由小到大全排列中的顺序,因此是可逆的。
公式:
将方案(0~8排列组成的)在0~8九个数的全排列中查找位置(康托展开函数):
int yasuo(char s[10])//s="012345678" -->x=1 { int p,sum=0;//p为在s[m]之前的数 for (int m=1;m<=9;m++) { p=0; for (int i=m+1;i<=9;i++) if (s[i]-'0'<s[m]-'0') p++;//每当有一个数比s[m]小,p++ if (m<9) sum+=p*jc[9-m];//jc数组里装的阶乘 else sum++;//注意最后sum要+1 } return sum;//宿命即位置 }
伪代码:
头=尾=1; while(头<=尾){ 取出最开始的头元素 压缩成数组; 四个方向循环{ 将转换后的状态储存 将转换后的状态解压成数字 求转换后的状态是第多少个 if(如果没有出现过){ 出现 将解压后的数字入队 步数为上一步的步数+1; 如果和要求的状态一样{ 输出 return; } } } 头指针++; }