双向bfs 学习笔记

双向bfs

很多题目会给你起点和终点,让你求起点到终点的一条最短路径(当然这是无权图);

这时可以用bfs,但是还不是最快的方法,当知道终点时,我们可以用双向bfs;

双向和单向的区别在于,可以从终点和起点同时出发,记录每个点是被从起点开始的访问了,还是被从终点开始的访问了,如果访问到一个点,同时被起点开始的和终点开始的访问了,那么这个点就是答案的必经点,输出起终路径之和就行;

模板题一:

八数码难题

模板:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
#define inf 0x3f3f3f3f
//ios::sync_with_stdio(false);
using namespace std;
const int N=200100;
const int M=1000100;
const LL mod=998244353;
string s;
map<string,int>ma;
map<string,int>vis;//0表示没访问,1表示正向,2表示反向
void bfs(){
	if(s=="123804765"){
		cout<<0<<endl;
		return;
	}
	queue<string>qu1,qu2;
	vis[s]=1,ma[s]=0;
	qu1.push(s);//正向
	vis["123804765"]=2,ma["123804765"]=1;
	qu2.push("123804765");//反向
	while(!qu1.empty()&&!qu2.empty()){
		int flag=0;
		string p;
		if(qu1.size()<qu2.size()){//谁结点少,先访问谁 
			p=qu1.front();
			qu1.pop();
			flag=1;	
		}
		else{
			p=qu2.front();
			qu2.pop();
			flag=2;	
		}
		int d;//0的位置
		for(int i=0;i<p.length();i++){
			if(p[i]=='0'){
				d=i;
				break;
			}
		}
		int x=d/3;
		int y=d%3;
		if(x>0){
			string q=p;
			char c=q[d];
			q[d]=q[3*(x-1)+y];
			q[3*(x-1)+y]=c;
			if(vis[q]==0){
				vis[q]=flag;
				ma[q]=ma[p]+1;
				if(flag==1) qu1.push(q);
				else qu2.push(q);
			}
			else if(vis[q]+vis[p]==3){
				cout<<ma[p]+ma[q]<<endl;
				return;
			}
		}
		if(x<2){
			string q=p;
			char c=q[d];
			q[d]=q[3*(x+1)+y];
			q[3*(x+1)+y]=c;
			if(vis[q]==0){
				vis[q]=flag;
				ma[q]=ma[p]+1;
				if(flag==1) qu1.push(q);
				else qu2.push(q);
			}
			else if(vis[q]+vis[p]==3){
				cout<<ma[p]+ma[q]<<endl;
				return;
			}
		}
		if(y>0){
			string q=p;
			char c=q[d];
			q[d]=q[3*x+y-1];
			q[3*x+y-1]=c;
			if(vis[q]==0){
				vis[q]=flag;
				ma[q]=ma[p]+1;
				if(flag==1) qu1.push(q);
				else qu2.push(q);
			}
			else if(vis[q]+vis[p]==3){
				cout<<ma[p]+ma[q]<<endl;
				return;
			}
		}
		if(y<2){
			string q=p;
			char c=q[d];
			q[d]=q[3*x+y+1];
			q[3*x+y+1]=c;
			if(vis[q]==0){
				vis[q]=flag;
				ma[q]=ma[p]+1;
				if(flag==1) qu1.push(q);
				else qu2.push(q);
			}
			else if(vis[q]+vis[p]==3){
				cout<<ma[p]+ma[q]<<endl;
				return;
			}
		}
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin>>s;
	bfs();
	return 0;
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值