题意
不能走到一起,或者穿着走,
将矩阵转化成图,双向比单向优化300+ms
单向bfs
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
char l[20][20];
int num[20][20],g[200][6],vis[200][200][200],s[26],t[26];
struct node
{
int a,b,c;
int cnt;
node(){};
node(int a,int b,int c,int cnt): a(a),b(b),c(c),cnt(cnt){}
};
void bfs()
{
int a1,b1,c1;
memset(vis,0,sizeof vis);
vis[s[0]][s[1]][s[2]] = 1;
queue<node> q;
node e;
e.a = s[0],e.b = s[1],e.c = s[2],e.cnt = 0;
q.push(e);
while(!q.empty()){
e = q.front();q.pop();
if(e.a == t[0] && e.b == t[1] && e.c == t[2]){
cout << e.cnt << endl;
return ;
}
for(int i = 0 ; i <= g[e.a][0];i++){
a1 = (i == 0 ? e.a:g[e.a][i]); //0的时候原地不动
for(int j = 0 ; j <= g[e.b][0];j++){
b1 = (j == 0 ? e.b:g[e.b][j]);
for(int k = 0 ; k <= g[e.c][0];k++){
c1 = (k == 0 ? e.c:g[e.c][k]);
if(vis[a1][b1][c1]) continue;
//不能在同一个点上
if((a1 && b1 && a1 == b1) || (a1 && c1 && a1 == c1) || (b1 && c1 && b1 == c1)) continue;
//不能穿过字母走
if(a1 && b1 && a1 == e.b && b1 == e.a) continue;
if(a1 && c1 && a1 == e.c && c1 == e.a) continue;
if(b1 && c1 && b1 == e.c && c1 == e.b) continue;
vis[a1][b1][c1] = 1;
q.push(node(a1,b1,c1,e.cnt+1));
}
}
}
}
}
int main()
{
int w,h,n;
while(cin >> w >> h >> n && w + h + n){
getchar();
for(int i = 0 ; i < h ; i++){
fgets(l[i],20,stdin);
}
//建图
//给图中的空白处编号
memset(num,0,sizeof num);
int cnt = 0;
for(int i = 0 ; i < h ; i++)
for(int j = 0 ; j < w ; j++)
if(l[i][j] != '#')
num[i][j] = ++cnt;
//邻接表存图
memset(g,0,sizeof g);
for(int i = 0 ; i < h ; i++){
for(int j = 0 ; j < w ; j++){
if(num[i][j]){
int pos = num[i][j];
if(num[i+1][j]) g[pos][++g[pos][0]] = num[i+1][j];
if(num[i-1][j]) g[pos][++g[pos][0]] = num[i-1][j];
if(num[i][j+1]) g[pos][++g[pos][0]] = num[i][j+1];
if(num[i][j-1]) g[pos][++g[pos][0]] = num[i][j-1];
}
}
}
//找到初始状态和最终状态
memset(s,0,sizeof s);
memset(t,0,sizeof t);
for(int i = 0 ; i < h ; i++){
for(int j = 0 ; j < w ; j++){
if(islower(l[i][j])) s[l[i][j] - 'a'] = num[i][j];
else if(isupper(l[i][j])) t[l[i][j] - 'A'] = num[i][j];
}
}
int m = 0;
for(int i = 0 ; i < 26 ; i++){
if(s[i]) s[m] = s[i],t[m++]=t[i];
}
if(n < 3) s[2] = 0,t[2] = 0;
if(n < 2) s[1] = 0,t[1] = 0;
bfs();
}
return 0;
}
双向bfs
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
char l[20][20];
int num[20][20],g[200][6],s[26],t[26];
int vis[200][200][200],vis1[200][200][200];
struct node
{
int a,b,c;
int cnt;
node(){};
node(int a,int b,int c,int cnt): a(a),b(b),c(c),cnt(cnt){}
};
void bfs()
{
int a1,b1,c1;
memset(vis,0,sizeof vis);
memset(vis1,0,sizeof vis1);
vis[s[0]][s[1]][s[2]] = 1;
vis1[t[0]][t[1]][t[2]] = 1;
queue<node> q;
queue<node> w;
node e,r;
q.push(node(s[0],s[1],s[2],1));
w.push(node(t[0],t[1],t[2],1));
while(!q.empty() && !w.empty()){
e = q.front();q.pop();
r = w.front();w.pop();
if(vis[r.a][r.b][r.c]){
cout << vis1[r.a][r.b][r.c] + vis[r.a][r.b][r.c] - 2 << endl;
return ;
}
else if(vis1[e.a][e.b][e.c]){
cout << vis1[e.a][e.b][e.c] + vis[e.a][e.b][e.c] - 2<< endl;
return;
}
for(int i = 0 ; i <= g[e.a][0];i++){
a1 = (i == 0 ? e.a:g[e.a][i]); //0的时候原地不动
for(int j = 0 ; j <= g[e.b][0];j++){
b1 = (j == 0 ? e.b:g[e.b][j]);
for(int k = 0 ; k <= g[e.c][0];k++){
c1 = (k == 0 ? e.c:g[e.c][k]);
if(vis[a1][b1][c1]) continue;
//不能在同一个点上
if((a1 && b1 && a1 == b1) || (a1 && c1 && a1 == c1) || (b1 && c1 && b1 == c1)) continue;
//不能穿过字母走
if(a1 && b1 && a1 == e.b && b1 == e.a) continue;
if(a1 && c1 && a1 == e.c && c1 == e.a) continue;
if(b1 && c1 && b1 == e.c && c1 == e.b) continue;
vis[a1][b1][c1] = e.cnt+1;
q.push(node(a1,b1,c1,e.cnt+1));
}
}
}
for(int i = 0 ; i <= g[r.a][0];i++){
a1 = (i == 0 ? r.a:g[r.a][i]); //0的时候原地不动
for(int j = 0 ; j <= g[r.b][0];j++){
b1 = (j == 0 ? r.b:g[r.b][j]);
for(int k = 0 ; k <= g[r.c][0];k++){
c1 = (k == 0 ? r.c:g[r.c][k]);
if(vis1[a1][b1][c1]) continue;
//不能在同一个点上
if((a1 && b1 && a1 == b1) || (a1 && c1 && a1 == c1) || (b1 && c1 && b1 == c1)) continue;
//不能穿过字母走
if(a1 && b1 && a1 == r.b && b1 == r.a) continue;
if(a1 && c1 && a1 == r.c && c1 == r.a) continue;
if(b1 && c1 && b1 == r.c && c1 == r.b) continue;
vis1[a1][b1][c1] = r.cnt+1;
w.push(node(a1,b1,c1,r.cnt+1));
}
}
}
}
}
int main()
{
int w,h,n;
while(cin >> w >> h >> n && w + h + n){
getchar();
for(int i = 0 ; i < h ; i++){
fgets(l[i],20,stdin);
}
//建图
//给图中的空白处编号
memset(num,0,sizeof num);
int cnt = 0;
for(int i = 0 ; i < h ; i++)
for(int j = 0 ; j < w ; j++)
if(l[i][j] != '#')
num[i][j] = ++cnt;
//邻接表存图
memset(g,0,sizeof g);
for(int i = 0 ; i < h ; i++){
for(int j = 0 ; j < w ; j++){
if(num[i][j]){
int pos = num[i][j];
if(num[i+1][j]) g[pos][++g[pos][0]] = num[i+1][j];
if(num[i-1][j]) g[pos][++g[pos][0]] = num[i-1][j];
if(num[i][j+1]) g[pos][++g[pos][0]] = num[i][j+1];
if(num[i][j-1]) g[pos][++g[pos][0]] = num[i][j-1];
}
}
}
//找到初始状态和最终状态
memset(s,0,sizeof s);
memset(t,0,sizeof t);
for(int i = 0 ; i < h ; i++){
for(int j = 0 ; j < w ; j++){
if(islower(l[i][j])) s[l[i][j] - 'a'] = num[i][j];
else if(isupper(l[i][j])) t[l[i][j] - 'A'] = num[i][j];
}
}
int m = 0;
for(int i = 0 ; i < 26 ; i++){
if(s[i]) s[m] = s[i],t[m++]=t[i];
}
if(n < 3) s[2] = 0,t[2] = 0;
if(n < 2) s[1] = 0,t[1] = 0;
bfs();
}
return 0;
}