`

搜索(二)——双向BFS

 
阅读更多

参考这篇文章,以下前部分为转载:http://www.cppblog.com/Yuan/archive/2011/02/23/140553.aspx

大牛,谢谢!不是你,我还在用交替节点搜索呢:{  ——应该用交替层次搜索

 

如果目标也已知的话,用双向BFS能很大提高速度。
单向时,是 b^len的扩展。双向的话,2*b^(len/2)  快了很多,特别是分支因子b较大时
至于实现上,网上有些做法是用两个队列,交替节点搜索 × ,如下面的伪代码:
    while(!empty()){
            扩展正向一个节点
            遇到反向已经扩展的return
            扩展反向一个节点     
            遇到正向已经扩展的return     
    }
但这种做法是有问题的,如下面的图:


求S-T的最短路,交替节点搜索(一次正向节点,一次反向节点)时

 

while(1):

S –> 1
T –> 3


while(2):

S -> 5

T -> 4

 

while(3):

1 -> 5

3 -> 5   返回最短路为4,错误的,事实是3,S-2-4-T

我想,正确做法的是交替逐层搜索 ,保证了不会先遇到非最优解就跳出,而是检查完该层所有节点,得到最优值。
也即如果该层搜索遇到了对方已经访问过的,那么已经搜索过的层数就是答案了,可以跳出了,以后不会更优的了。
当某一边队列空时就无解了。
 
优化:提供速度的关键在于使状态扩展得少一些,所以优先选择队列长度较少的去扩展,保持两边队列长度平衡。这比较适合于两边的扩展情况不同时,一边扩展得快,一边扩展得慢。如果两边扩展情况一样时,加了后效果不大,不过加了也没事。
无向图时,两边扩展情况类似。有向图时,注意反向的扩展是反过来的 x->y(如NOIP2002G2字串变换)


例题:

POJ1915

#include <stdio.h>
#include <stdlib.h>
#include <queue>
#include <iostream>
using namespace std;

int l; //4<=l<=300
int sx,sy,tx,ty;
int a[305][305];	//正向搜索层次
int b[305][305];	//反向搜索层次

struct point{
	int x,y;
};

struct point dir[]=
	{
	{1,2},{1,-2},{-1,2},{-1,-2},
	{2,1},{2,-1},{-2,1},{-2,-1}
	};

bool check(int x,int y){
	if(x>=0 && x<l && y>=0 && y<l)
		return true;
	else
		return false;
}

void dbfs(){
	memset(a,-1,sizeof(a));
	memset(b,-1,sizeof(b));
	a[sx][sy]=0;
	b[tx][ty]=0;

	queue<point> forQ,backQ;
	point p1,p2;
	p1.x=sx;
	p1.y=sy;
	p2.x=tx;
	p2.y=ty;
	forQ.push(p1);
	backQ.push(p2);
	
	//正反向队列至少还有一个可以扩展
	while(forQ.empty()==false || backQ.empty()==false){
		//优化:优先扩展元素少的队列(如果只有一个队列非空,则扩展非空队列)
		int forSize=forQ.size();
		int backSize=backQ.size();

		if(backSize==0 || forSize<backSize){
			//扩展正向队列一层
			int i;
			for(i=0;i<forSize;i++){
				point cur=forQ.front();
				forQ.pop();

				if(b[cur.x][cur.y]!=-1){
					printf("%d\n",a[cur.x][cur.y]+b[cur.x][cur.y]);
					return;
				}

				int j;
				for(j=0;j<8;j++){
					if(check(cur.x+dir[j].x, cur.y+dir[j].y)){
						point next={cur.x+dir[j].x, cur.y+dir[j].y};	//!注意struct的创建方式
						
						if(a[next.x][next.y]!=-1)//以前已经正向扩展过
							continue;

						a[next.x][next.y]=a[cur.x][cur.y]+1;

						forQ.push(next);
					}
				}
			}
		}else{
			//扩展反向队列一层
			int i;
			for(i=0;i<backSize;i++){
				point cur=backQ.front();
				backQ.pop();

				if(a[cur.x][cur.y]!=-1){
					printf("%d\n",a[cur.x][cur.y]+b[cur.x][cur.y]);
					return;
				}

				int j;
				for(j=0;j<8;j++){
					if(check(cur.x+dir[j].x, cur.y+dir[j].y)){
						point next={cur.x+dir[j].x, cur.y+dir[j].y};
						
						if(b[next.x][next.y]!=-1)
							continue;

						b[next.x][next.y]=b[cur.x][cur.y]+1;

						backQ.push(next);
					}
				}
			}
		}
	}//end while

	printf("0");
}

int main(void){
	int time;
	scanf("%d",&time);
	while(time-->0){
		scanf("%d%d%d%d%d\n",&l,&sx,&sy,&tx,&ty);
		dbfs();
	}

	return 0;
}
 

poj 1077 :Eight

 

 

 

  • 大小: 11.4 KB
分享到:
评论

相关推荐

    数据结构、算法与应用:C++语言描述(原书第2版)第二部分

    16.8.3 方法graph::bfs的复杂性分析 16.8.4 深度优先搜索 16.8.5 深度优先搜索的实现 16.8.6 方法graph::dfs的复杂性分析 16.9 应用 16.9.1 寻找一条路径 16.9.2 连通图及其构成 16.9.3 生成树 第三部分 算法...

    数据结构与算法:C++描述

    本书是关于计算机科学与工程领域的基础性研究科目之一——数据结构与算法的专著。 本书在简要回顾了基本的C++ 程序设计概念的基础上,全面系统地介绍了队列、堆栈、树、图等基本数据结构,以及贪婪算法、分而治之...

    数据结构算法与应用-C__语言描述

    本书是关于计算机科学与工程领域的基础性研究科目之一——数据结构与算法的专著。 本书在简要回顾了基本的C++ 程序设计概念的基础上,全面系统地介绍了队列、堆栈、树、图等基本数据结构,以及贪婪算法、分而治之...

    C++语言描述(PDF合集)

    3.4.7 双向链表 95 3.4.8 小结 96 3.5 间接寻址 99 3.5.1 基本概念 99 3.5.2 操作 100 3.6 模拟指针 102 3.6.1 SimSpace的操作 103 3.6.2 采用模拟指针的链表 106 3.7 描述方法的比较 110 3.8 应用 111 3.8.1 箱子...

    数据结构算法与应用-C++语言描述

    本书是关于计算机科学与工程领域的基础性研究科目之一——数据结构与算法的专著。 本书在简要回顾了基本的C++ 程序设计概念的基础上,全面系统地介绍了队列、堆栈、树、图等基本数据结构,以及贪婪算法、分而治之...

    数据结构算法与应用(C++语言描述).rar

    3.4.7 双向链表 95 3.4.8 小结 96 3.5 间接寻址 99 3.5.1 基本概念 99 3.5.2 操作 100 3.6 模拟指针 102 3.6.1 SimSpace的操作 103 3.6.2 采用模拟指针的链表 106 3.7 描述方法的比较 110 3.8 应用 111 3.8.1 箱子...

    数据结构C++描述

    3.4.7 双向链表 95 3.4.8 小结 96 3.5 间接寻址 99 3.5.1 基本概念 99 3.5.2 操作 100 3.6 模拟指针 102 3.6.1 SimSpace的操作 103 3.6.2 采用模拟指针的链表 106 3.7 描述方法的比较 110 3.8 应用 111 3.8.1 箱子...

    数据结构 C++描述

    3.4.7 双向链表 95 3.4.8 小结 96 3.5 间接寻址 99 3.5.1 基本概念 99 3.5.2 操作 100 3.6 模拟指针 102 3.6.1 SimSpace的操作 103 3.6.2 采用模拟指针的链表 106 3.7 描述方法的比较 110 3.8 应用 111 3.8.1 箱子...

    数据结构、算法与应用--C++语言描述

    3.4.7 双向链表 95 3.4.8 小结 96 3.5 间接寻址 99 3.5.1 基本概念 99 3.5.2 操作 100 3.6 模拟指针 102 3.6.1 SimSpace的操作 103 3.6.2 采用模拟指针的链表 106 3.7 描述方法的比较 110 3.8 应用 111 3.8.1 箱子...

    数据结构(C语言描述)

    3.4.7 双向链表 95 3.4.8 小结 96 3.5 间接寻址 99 3.5.1 基本概念 99 3.5.2 操作 100 3.6 模拟指针 102 3.6.1 SimSpace的操作 103 3.6.2 采用模拟指针的链表 106 3.7 描述方法的比较 110 3.8 应用 111 3.8.1 箱子...

    数据结构算法与应用-C C++语言描述

    7.5 应用——文本压缩 238 7.5.1 LZW压缩 239 7.5.2 LZW压缩的实现 239 7.5.3 LZW解压缩 243 7.5.4 LZW解压缩的实现 243 7.6 参考及推荐读物 247 第8章 二叉树和其他树 248 8.1 树 248 8.2 二叉树 251 8.3 二叉树的...

    数据结构算法与应用-C++语言描述.rar

    7.5 应用——文本压缩 238 7.5.1 LZW压缩 239 7.5.2 LZW压缩的实现 239 7.5.3 LZW解压缩 243 7.5.4 LZW解压缩的实现 243 7.6 参考及推荐读物 247 第8章 二叉树和其他树 248 8.1 树 248 8.2 二叉树 251 8.3 ...

    数据结构算法与应用 很详细的,数据结构算法全集 这个是你想找的

    搜索树 319 11.1 二叉搜索树 320 11.1.1 基本概念 320 11.1.2 抽象数据类型BSTree和 IndexedBSTree 321 11.1.3 类BSTree 322 11.1.4 搜索 322 11.1.5 插入 323 11.1.6 删除 324 11.1.7 ...

    ACM程序设计培训教程

     1.6.5 计算式查找法——哈希法…………………………………………………28  1.7 排序的基本概念……………………………………………………………………33  1.7.1 插入类排序………………………………………………...

Global site tag (gtag.js) - Google Analytics