1. 程式人生 > >【UVa】【雙向BFS】1601 The Morning after Halloween

【UVa】【雙向BFS】1601 The Morning after Halloween

UVa 1601 The Morning after Halloween

題目

題目大意

在一個W×HW\times H的網格上有N(N3)N(N\le3)個鬼,用小寫字母表示。要求將所有鬼移動到對應的大寫字母處。每步可以有多個鬼移動(均為上下左右四個方向之一),但每步結束之後任何兩個鬼不能再同一個位置,也不能在一步之內交換位置。舉個例子: 它有四種移動方式: 輸入保證所有的空格連通,所有的障礙格也連通,且每個2×22\times2的格子中有至少一個障礙格。輸出最少的移動步數。

思路

P.s.如果有想看BFS版的讀者請點這裡

相信大家都清楚了本題的思路,所以這裡只簡述一下雙向BFS的注意的地方。

首先,我們必須注意,雙向BFS每次必須擴充套件一層節點,而不是一個節點。

舉個例子:

其次,由於這道題資料範圍較小,所以我們可以暴力採用陣列判重。

其他細節詳見程式碼。

正解程式碼

#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int Maxw=20;
const int Maxn=150;
const int dir[][2]={{1,0},{-1,0}
,{0,1},{0,-1},{0,0}}; int W,H,N,cnt; char Map[Maxw+5][Maxw+5]; int s[3],t[3]; vector<int> G[Maxn+5]; int id[Maxw+5][Maxw+5]; int X[Maxn+5],Y[Maxn+5]; void Prepare() { memset(G,0,sizeof G); cnt=0; for(int i=0;i<H;i++) for(int j=0;j<W;j++) if(Map[i][j]!='#') { X[cnt]=i,Y[cnt]=j; id[
i][j]=cnt; if('a'<=Map[i][j]&&Map[i][j]<='z') s[Map[i][j]-'a']=cnt; if('A'<=Map[i][j]&&Map[i][j]<='Z') t[Map[i][j]-'A']=cnt; cnt++; } } void BuildGraph() { for(int i=0;i<cnt;i++) for(int j=0;j<5;j++) { int tx=X[i]+dir[j][0],ty=Y[i]+dir[j][1]; if(Map[tx][ty]!='#') G[i].push_back(id[tx][ty]); } if(N<=2) { G[cnt].push_back(cnt); s[2]=t[2]=cnt; cnt++; } if(N<=1) { G[cnt].push_back(cnt); s[1]=t[1]=cnt; cnt++; } } int d[Maxn+5][Maxn+5][Maxn+5]; int col[Maxn+5][Maxn+5][Maxn+5]; queue<int> q[2]; inline void clear() { memset(d,-1,sizeof d); memset(col,-1,sizeof col); while(!q[0].empty())q[0].pop(); while(!q[1].empty())q[1].pop(); } inline int getid(int a,int b,int c) { return (a<<16)|(b<<8)|c; } inline bool ok(int a1,int b1,int a2,int b2) { if(a2==b2||(a2==b1&&b2==a1)) return false; return true; } inline int BFS(int id) { int siz=q[id].size(); while(siz--) { int u=q[id].front();q[id].pop(); int a=(u>>16)&0xFF,b=(u>>8)&0xFF,c=u&0xFF; for(int i=0;i<G[a].size();i++) { int ta=G[a][i]; for(int j=0;j<G[b].size();j++) { int tb=G[b][j]; if(!ok(a,b,ta,tb))continue; for(int k=0;k<G[c].size();k++) { int tc=G[c][k]; if(!ok(a,c,ta,tc))continue; if(!ok(b,c,tb,tc))continue; if(col[ta][tb][tc]==-1) { col[ta][tb][tc]=id; d[ta][tb][tc]=d[a][b][c]+1; q[id].push(getid(ta,tb,tc)); } else if(col[ta][tb][tc]==(!id)) return d[ta][tb][tc]+d[a][b][c]; } } } } return -1; } int BFS() { clear(); q[0].push(getid(s[0],s[1],s[2])); q[1].push(getid(t[0],t[1],t[2])); d[s[0]][s[1]][s[2]]=0; d[t[0]][t[1]][t[2]]=1; col[s[0]][s[1]][s[2]]=0; col[t[0]][t[1]][t[2]]=1; while(!q[0].empty()||!q[1].empty()) { int t=BFS(0); if(t!=-1)return t; t=BFS(1); if(t!=-1)return t; } return -1; } int main() { #ifdef LOACL freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif while(scanf("%d %d %d\n",&W,&H,&N)==3&&N) { for(int i=0;i<H;i++) fgets(Map[i],20,stdin); Prepare(); BuildGraph(); printf("%d\n",BFS()); } return 0; }