按照紫书的做法,创建两个对列,进行双向的BFS搜索,即可。具体实现见如下代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
using namespace std;
int w, h, n;
int dx[] = {0,1,-1,0,0};
int dy[] = {0,0,0,1,-1};
string *area;
int Start[3], End[3];
int Length[270];
int Edge[270][270];
int d1[270][270][270], d2[270][270][270];
int ID(int a, int b, int c){
return (a << 16) | (b << 8) | (c);
}
bool feasible(int a,int a1,int b,int b1){
if (a1 == b1 || (a==b1&&a1==b)) return false;
return true;
}
int D_BFS(){
queue<int> q1, q2;
q1.push(ID(Start[0],Start[1],Start[2]));
q2.push(ID(End[0], End[1], End[2]));
memset(d1, -1, sizeof(d1));
memset(d2, -1, sizeof(d2));
d1[Start[0]][Start[1]][Start[2]] = 0;
d2[End[0]][End[1]][End[2]] = 0;
while (!q1.empty()&&!q2.empty()){
queue<int> next_s;
if (q1.size() < q2.size()){
while (!q1.empty()){
int front = q1.front(); q1.pop();
int a, b, c;
a = (front >> 16) & 0xff; b = (front >> 8) & 0xff; c = (front)& 0xff;
for (int i = 0; i < Length[a]; i++){
int a1 = Edge[a][i];
for (int j = 0; j < Length[b]; j++){
int b1 = Edge[b][j];
if (!feasible(a, a1, b, b1)) continue;
for (int k = 0; k < Length[c]; k++){
int c1 = Edge[c][k];
if (!feasible(a, a1, c, c1) || !feasible(b, b1, c, c1) || d1[a1][b1][c1] != -1) continue;
d1[a1][b1][c1] = d1[a][b][c] + 1;
if (d2[a1][b1][c1] != -1) return d1[a1][b1][c1] + d2[a1][b1][c1];
if (a1 == End[0] && b1 == End[1] && c1 == End[2]) return d1[a1][b1][c1];
next_s.push(ID(a1, b1, c1));
}
}
}
}
q1 = next_s;
}
else{
while (!q2.empty()){
int front = q2.front(); q2.pop();
int a, b, c;
a = (front >> 16) & 0xff; b = (front >> 8) & 0xff; c = (front)& 0xff;
for (int i = 0; i < Length[a]; i++){
int a1 = Edge[a][i];
for (int j = 0; j < Length[b]; j++){
int b1 = Edge[b][j];
if (!feasible(a, a1, b, b1)) continue;
for (int k = 0; k < Length[c]; k++){
int c1 = Edge[c][k];
if (!feasible(a, a1, c, c1) || !feasible(b, b1, c, c1) || d2[a1][b1][c1] != -1) continue;
d2[a1][b1][c1] = d2[a][b][c] + 1;
if (d1[a1][b1][c1] != -1) return d1[a1][b1][c1] + d2[a1][b1][c1];
if (a1 == Start[0] && b1 == Start[1] && c1 == Start[2]) return d2[a1][b1][c1];
next_s.push(ID(a1, b1, c1));
}
}
}
}
q2 = next_s;
}
}
return -1;
}
int main(){
while (cin >> w >> h >> n){
if (w == 0 && h == 0 && n == 0) break;
string del; getline(cin, del);
area = new string[h];
for (int i = 0; i < h; i++) getline(cin, area[i]);
int index = 0;
int id[270][270], x[270], y[270];
memset(id,-1,sizeof(id));
memset(x, -1, sizeof(x));
memset(y, -1, sizeof(y));
for (int i = 0; i < h; i++){
for (int j = 0; j < w; j++){
if (area[i][j] != '#'){
x[index] = i; y[index] = j; id[i][j] = index;
if (area[i][j] >= 'a'&&area[i][j] <= 'z') Start[area[i][j] - 'a']=index;
if (area[i][j] >= 'A'&&area[i][j] <= 'Z') End[area[i][j] - 'A'] = index;
index++;
}
}
}
memset(Length,0,sizeof(Length));
for (int i = 0; i < index; i++){
int tx = x[i], ty = y[i];
for (int j = 0; j < 5; j++){
int newx = tx + dx[j], newy = ty + dy[j];
if (newx >= 0 && newx < h&&newy >= 0 && newy < w&&area[newx][newy] != '#'){
Edge[i][Length[i]] = id[newx][newy];
Length[i]++;
}
}
}
if (n <= 1){
Start[1] = End[1] = index;
Length[index] = 1;
Edge[index][0] = index;
index++;
}
if (n <= 2){
Start[2] = End[2] = index;
Length[index] = 1;
Edge[index][0] = index;
index++;
}
cout << D_BFS() << endl;
}
return 0;
}