用双向宽搜来提高搜索效率

   在信息竞赛中,常常会遇到一些用广度优先搜索才能实现的题目,而这类题目很大一部分都可以用双向宽搜来提高搜索速度,

这类题目的共同点是:

   1。   起始状态和目标状态都很明确;

   2。  搜索一条从起始状态道目标状态的最短路径。

   3。 规则具有对称性,既如果原规则向左,则其相反规则就是向右,双向时,从目标状态像起始状态搜索时,需要将规则对称。


双向宽搜的思路为分别以目标状态和初始状态为起点,分别扩展节点,当扩展到相同的节点时,就找到了目标,最短路径为起始状态和目标状态到搜索到的点的路径之和。下面附图

用双向宽搜来提高搜索效率_第1张图片


具体实现过程如下(C++党老老实实的手打队列吧哈哈)

int head[2],tail[2],queue[maxn][2],ji[maxn][2];

void checkmeet(int t)
{
	检查新扩展的节点是否在另一个搜索状态中出现过;
	出现过:输出并退出程序; 
} 

void expand(int t)
{
	head[t]++;
	for(按规则扩展)
	{
		判重;
		入队;
		checkmeet(t); //检查是否相遇 
	} 
}

void DoubleBFS()
{
	head[0]=;tail[0]=;
	head[1]=;tail[1]=;
	queue[1][1]=目标状态;
	queue[0][1]=起始状态;
	ji[1][1]=;
	ji[0][1]=;        //初始化
	while(head[0]




经典例题  八数码简单题:


#include
#include
#include
#include
#include 

using namespace std;
string st,en;
int ans,head[2],tail[2];
string s[100005][2];
int    b[100005][2];
sethash[2];

void checkmeet(int t)
{
	if(hash[1-t].count(s[tail[t]][t]))
	{
		for(int i=1;i<=tail[1-t];i++)
		if(s[i][1-t]==s[tail[t]][t])
		{
			printf("%d\n",b[i][1-t]+b[tail[t]][t]);
			break;
		}
		exit(0);
	}
}

string get(string s,int i)
{
	string t=s;
	int lwz=s.find('0');
	if(i==1)
	{
		if(lwz<3) return "-1";
		swap(t[lwz],t[lwz-3]);
		return t;
	}
	if(i==2)
	{
		if(lwz==0||lwz==3||lwz==6) return "-1";
		swap(t[lwz],t[lwz-1]);
		return t;
	}
	if(i==3)
	{
		if(lwz>5) return "-1";
		swap(t[lwz],t[lwz+3]);
		return t;
	}
	if(i==4)
	{
		if(lwz==2||lwz==5||lwz==8) return "-1";
		swap(t[lwz],t[lwz+1]);
		return t;
	}
}

void expand(int t)
{
	head[t]++;
	string ss=s[head[t]][t];
	int c=b[head[t]][t]+1;
	for(int i=1;i<=4;i++)
	{
		string stmp=get(ss,i);
		if(stmp=="-1"||hash[t].count(stmp))continue;
		else
		{
			hash[t].insert(stmp);
			tail[t]++;
			b[tail[t]][t]=c;
			s[tail[t]][t]=stmp;
			checkmeet(t);
		}
	}	
}

void DoubleBFS()
{
	head[0]=0;tail[0]=1;
	head[1]=0;tail[1]=1;
	s[1][0]=st;
	s[1][1]="123804765";
	while(head[0]>st;
	DoubleBFS();
}



你可能感兴趣的:(基础)