题意
问移动图上三个Ghost同时到达目标点的最短步数。三个Ghost可以同时移动,但不能重叠,不能交换位置。
双向BFS做法
因为状态比较多,直接BFS会T,因此用双向BFS来优化。然而直接上双向BFS还是会T,在BFS过程中枚举可以走的循环太多了,因此对图进行预处理,取出所有可以走的点进行BFS。16*16不是太多,所以没有必要hash,直接开个六维数组还方便些。其他就是一些双向BFS常规注意的地方了,比如一层一层交替更新之类的。
//UVA 1601 The Morning after Halloween
//AC 2016-7-25 11:15:26
//Two-way BFS
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <set>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <list>
#include <sstream>
#include <stack>
using namespace std;
#define cls(x) memset(x,0,sizeof x)
#define inf(x) memset(x,0x3f,sizeof x)
#define neg(x) memset(x,-1,sizeof x)
#define ninf(x) memset(x,0xc0,sizeof x)
#define st0(x) memset(x,false,sizeof x)
#define st1(x) memset(x,true,sizeof x)
#define INF 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define bug cout<<"here"<<endl;
//#define debug
int w,h,n;
struct node
{
int x[3],y[3];
int steps;
node():steps(0){cls(x);cls(y);}
void clear(){steps=0;cls(x);cls(y);}
node& operator= (node &rhs)
{
for(int i=0;i<3;++i)
{
x[i]=rhs.x[i];
y[i]=rhs.y[i];
}
steps=rhs.steps;
return *this;
}
}p,q;
int G[20][20];
const int dx[]={0,-1,1,0,0};
const int dy[]={0,0,0,1,-1};
vector<pair<int,int> > GA[20][20];
inline bool legal(const node &pre,const node &now)
{
bool res=1;
for(int i=0;i<n;++i)
{
for(int j=0;j<n;++j)
{
if(j!=i)
{
res&=(now.x[i]!=now.x[j]||now.y[i]!=now.y[j]);
res&=!(now.x[i]==pre.x[j]&&pre.x[i]==now.x[j]&&now.y[i]==pre.y[j]&&now.y[j]==pre.y[i]);
}
}
}
return res;
}
queue<node> pque,rque;
int dist[20][20][20][20][20][20];
int visit[20][20][20][20][20][20];
#define Dist(a) dist[a.x[0]][a.y[0]][a.x[1]][a.y[1]][a.x[2]][a.y[2]]
#define Visit(a) visit[a.x[0]][a.y[0]][a.x[1]][a.y[1]][a.x[2]][a.y[2]]
int BFS()
{
while(pque.size())pque.pop();
while(rque.size())rque.pop();
pque.push(p);rque.push(q);
inf(dist);cls(visit);
Dist(p)=Dist(q)=0;
Visit(p)=1;Visit(q)=2;
int li,lj,lk;
while(pque.size()||rque.size())
{
if(pque.size()&&pque.size()<=rque.size())
{
int cur=pque.front().steps;
while(pque.size()&&pque.front().steps==cur)
{
p=pque.front();pque.pop();
vector<pair<int,int> > &g1=GA[p.x[0]][p.y[0]],&g2=GA[p.x[1]][p.y[1]],&g3=GA[p.x[2]][p.y[2]];
li=g1.size();
lj=(n>=2?g2.size():1);
lk=(n==3?g3.size():1);
for(int i=0;i<li;++i)
{
for(int j=0;j<lj;++j)
{
for(int k=0;k<lk;++k)
{
if(i==j&&j==k&&i==0)
continue;
q.x[0]=g1[i].first;q.y[0]=g1[i].second;
if(n>=2)
{
q.x[1]=g2[j].first;
q.y[1]=g2[j].second;
}
if(n==3)
{
q.x[2]=g3[k].first;
q.y[2]=g3[k].second;
}
q.steps=p.steps+1;
if(legal(p,q))
{
if(Visit(q)==2)
return Dist(q)+q.steps;
if(Visit(q)==0)
{
if(Dist(q)>q.steps)
{
Dist(q)=q.steps;
Visit(q)=1;
pque.push(q);
}
}
}
}
}
}
}
}
else if(rque.size())
{
int cur=rque.front().steps;
while(rque.size()&&rque.front().steps==cur)
{
p=rque.front();rque.pop();
vector<pair<int,int> > &g1=GA[p.x[0]][p.y[0]],&g2=GA[p.x[1]][p.y[1]],&g3=GA[p.x[2]][p.y[2]];
li=g1.size();
lj=(n>=2?g2.size():1);
lk=(n==3?g3.size():1);
for(int i=0;i<li;++i)
{
for(int j=0;j<lj;++j)
{
for(int k=0;k<lk;++k)
{
if(i==j&&j==k&&i==0)
continue;
q.x[0]=g1[i].first;q.y[0]=g1[i].second;
if(n>=2)
{
q.x[1]=g2[j].first;
q.y[1]=g2[j].second;
}
if(n==3)
{
q.x[2]=g3[k].first;
q.y[2]=g3[k].second;
}
q.steps=p.steps+1;
if(legal(p,q))
{
if(Visit(q)==1)
return Dist(q)+q.steps;
if(Visit(q)==0)
{
if(Dist(q)>q.steps)
{
Dist(q)=q.steps;
Visit(q)=2;
rque.push(q);
}
}
}
}
}
}
}
}
}
}
int main()
{
#ifdef debug
freopen("E:\Documents\code\input.txt","r",stdin);
freopen("E:\Documents\code\output.txt","w",stdout);
#endif
while(cin>>w>>h>>n&&w+h+n)
{
getchar();
char c;
cls(G);p.clear();q.clear();
for(int i=0;i<h;++i)
{
for(int j=0;j<w;++j)
{
c=getchar();
if(c=='#')G[i][j]=0;
else
{
G[i][j]=1;
if(c=='A')
{
p.x[0]=i;p.y[0]=j;
}
if(c=='B')
{
p.x[1]=i;p.y[1]=j;
}
if(c=='C')
{
p.x[2]=i;p.y[2]=j;
}
if(c=='a')
{
q.x[0]=i;q.y[0]=j;
}
if(c=='b')
{
q.x[1]=i;q.y[1]=j;
}
if(c=='c')
{
q.x[2]=i;q.y[2]=j;
}
}
}
getchar();
}
for(int i=0;i<=h;++i)
for(int j=0;j<=w;++j)
GA[i][j].clear();
int nx,ny;
for(int i=0;i<h;++i)
{
for(int j=0;j<w;++j)
{
if(G[i][j])
{
for(int k=0;k<5;++k)
{
nx=i+dx[k];ny=j+dy[k];
if(G[nx][ny]&&nx>=0&&nx<h&&ny>=0&&ny<w)
GA[i][j].push_back(make_pair(nx,ny));
}
}
}
}
cout<<BFS()<<endl;
}
return 0;
}
A*做法
(待补充……)