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

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

这类题目的共同点是:

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

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

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


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



具体实现过程如下(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]<tail[0]&&head[1]<tail[1])
	{
		if(tail[0]<tail[1])
		expand(0);
		else
		expand(1); 
	} 
} 




经典例题  八数码简单题:


#include<cstdio>
#include<iostream>
#include<set>
#include<string.h>
#include <cstdlib>

using namespace std;
string st,en;
int ans,head[2],tail[2];
string s[100005][2];
int    b[100005][2];
set<string>hash[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]<tail[0]&&head[1]<tail[1])
	if(tail[0]<tail[1])expand(0);else expand(1);
}

int main()
{
	cin>>st;
	DoubleBFS();
}



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值