双向广度优先搜索
首先需要优化转移代价 https://blog.csdn.net/qq_42835910/article/details/86513282
实现:正着搜索一层,反着搜索一层(注意是一层一层的,不是一个一个),然后继续这样交替下去,直到两层中出现相同的状态。
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int maxn=256;
vector<int> g[maxn];
string map[16];
int up[3],low[3],dx[5]={1,0,-1,0,0}, dy[5]={0,1,0,-1,0};
struct Node{
int a,b,c,step;
Node(int x,int y,int z,int step): a(x),b(y),c(z),step(step){ };
};
bool conflict(int a,int b,int x,int y){
return x==y || (a==y && b==x);
}
short vis[maxn][maxn][maxn];
bool bfs(int mark,int &step,queue<Node> &q){
while(!q.empty()){
Node u=q.front();
if(u.step>step) { step++; return false; }
q.pop();
int a=u.a,b=u.b,c=u.c;
for(int i=0;i<g[a].size();i++){
int x=g[a][i];
for(int j=0;j<g[b].size();j++){
int y=g[b][j];
if(conflict(a,b,x,y)) continue;
for(int k=0;k<g[c].size();k++){
int z=g[c][k];
if(conflict(a,c,x,z) || conflict(b,c,y,z) || vis[x][y][z]==mark) continue;
if(vis[x][y][z]) return true;
vis[x][y][z]=mark;
q.push(Node(x,y,z,u.step+1));
}
}
}
}
return false;
}
int twoBfs(){
if(low[0]==up[0] && low[1]==up[1] && low[2]==up[2]) return 0;
memset(vis,0,sizeof(vis));
queue<Node> p,q;
const int markP=1,markQ=2;
p.push(Node(low[0],low[1],low[2],0));
q.push(Node(up[0],up[1],up[2],0));
vis[up[0]][up[1]][up[2]]=markQ,vis[low[0]][low[1]][low[2]]=markP;
int stepP=0,stepQ=0;
while(!p.empty() && !q.empty()){
if(bfs(markP,stepP,p) || bfs(markQ,stepQ,q)) return stepP+stepQ+1;
}
return -1;
}
int main(int argc, char** argv) {
int w,h,n;
while(cin>>w>>h>>n && w ){
getline(cin,map[0]);
for(int i=0;i<h;i++) getline(cin,map[i]);
for(int i=0;i<maxn;i++) g[i].clear();
for(int i=0;i<h;i++){//将迷宫优化为图。
for(int j=0;j<w;j++){
if(map[i][j]!='#'){
for(int k=0;k<5;k++){
int x=i+dx[k],y=j+dy[k];
char c=map[x][y];
if(c!='#'){
int a=i*w+j,b=x*w+y;
if(isupper(c)) up[c-'A']=b;
else if(islower(c)) low[c-'a']=b;
g[a].push_back(b);
}
}
}
}
}
if(n<3){//添加伪节点,满足3个节点
up[2]=low[2]=0; g[0].push_back(0);
if(n<2) up[1]=low[1]=1; g[1].push_back(1);
}
cout<<twoBfs()<<endl;
}
return 0;
}