Ideas:
Starting from s (seen as a lot of people) meaning can go from multiple directions, to find the shortest path to A's. As a find A, then starting from the current position at this time and the number of steps is 0, and went to look for other A.
Can also direct violence to solve each letter of the path to the other letters were built map, set off from each letter, multiple BFS can be solved.
code :
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 55, M = N * N;
int n, m, t, sx, sy, cnt, mcnt, path[N][N], id[N][N], p[N]; //代表某个字母到达(i, j)的距离
char g[N][N];
int dx[4] = {1, 0, 0, -1};
int dy[4] = {0, 1, -1, 0};
struct Node {
int x, y, sx, sy, d;
Node(int x, int y, int sx, int sy, int d): x(x), y(y), sx(sx), sy(sy), d(d){}
bool operator < (const Node&o) const {
return d > o.d;
}
};
struct E {
int u, v, w;
bool operator < (const E&o) const {
return w < o.w;
}
} e[M];
int find(int x){return x == p[x] ? x : (p[x] = find(p[x]));}
void bfs() {
priority_queue<Node> q;
path[sx][sy] = 0;
id[sx][sy] = ++cnt; //给每个字母标号
q.push(Node(sx, sy, sx, sy, 0));
while (!q.empty()) {
Node t = q.top();
q.pop();
for (int i = 0; i < 4; i++) {
int fx = t.x + dx[i];
int fy = t.y + dy[i];
if (fx >= 0 && fy >= 0 && fx < n && fy < m && g[fx][fy] != '#') {
if (t.d + 1 < path[fx][fy]) {
if (t.sx == fx && t.sy == fy) continue;//避免自己与自己连边
path[fx][fy] = t.d + 1;
if (g[fx][fy] == 'A') {
q.push(Node(fx, fy, fx, fy, 0));
if (!id[fx][fy]) id[fx][fy] = ++cnt;
//添加边
e[++mcnt].u = id[t.sx][t.sy];
e[mcnt].v = id[fx][fy];
e[mcnt].w = t.d + 1;
} else {
q.push(Node(fx, fy, t.sx, t.sy, path[fx][fy]));
}
}
}
}
}
}
int main() {
scanf("%d", &t);
while (t--) {
memset(path, 0x3f, sizeof(path)); cnt = mcnt = 0;
memset(id, 0, sizeof(id));
scanf("%d%d", &m, &n);
gets(g[0]); //消除上面的换行
for (int i = 0; i < n; i++) gets(g[i]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (g[i][j] == 'S') sx = i, sy = j;
}
}
bfs(); //确定字母之间的关系
int ans = 0;
sort(e + 1, e + 1 + mcnt);
for (int i = 1; i <= cnt; i++) p[i] = i; //初始化并查集
for (int i = 1; i <= mcnt; i++) {
int fu = find(e[i].u), fv = find(e[i].v);
if (fu != fv) {
ans += e[i].w;
p[fu] = fv;
}
}
printf("%d\n", ans);
}
return 0;
}