对每一个人'用一次BFS,记录其他人与他的距离,并建图。
图建好后,用Prim求最小生成树即为答案。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; #define M 105 #define VN 2500 #define INF 1000000000 int map[M][M], dist[M][M], que_x[VN], que_y[VN], g[M][M]; int r, c, dir[4][2] = { {-1, 0}, {0, -1}, {1, 0}, {0, 1} }; bool visit[M / 2][M / 2]; void BFS(int x, int y) { memset(visit, false, sizeof(visit)); memset(dist, 0, sizeof(dist)); int head, tail, tmp_x, tmp_y, i, j; visit[x][y] = true; dist[x][y] = 0; head = 0; tail = 1; que_x[0] = x; que_y[0] = y; while (head < tail) { tmp_x = que_x[head]; tmp_y = que_y[head]; head++; for (i = 0; i < 4; i++) { int tx = tmp_x + dir[i][0]; int ty = tmp_y + dir[i][1]; if (tx > 0 && tx < r && ty > 0 && ty < c && !visit[tx][ty] && map[tx][ty] >= 0) { dist[tx][ty] = dist[tmp_x][tmp_y] + 1; visit[tx][ty] = true; que_x[tail] = tx; que_y[tail] = ty; tail++; if (map[tx][ty] > 0) { g[map[x][y]][map[tx][ty]] = dist[tx][ty]; g[map[tx][ty]][map[x][y]] = dist[tx][ty]; } } } } } int Prim(int start, int num) { bool vis[VN]; int d[VN], i, j, tmp, cur, ans = 0; memset(vis, false, sizeof(vis)); for (i = 2; i <= num; i++) d[i] = INF; d[1] = 0; for (i = 1; i <= num; i++) { tmp = INF; cur = -1; for (j = 1; j <= num; j++) { if (!vis[j] && d[j] < tmp) { tmp = d[j]; cur = j; } } if (cur == -1) break; ans += tmp; vis[cur] = true; for (j = 1; j <= num; j++) if (!vis[j] && g[cur][j] < d[j]) d[j] = g[cur][j]; } return ans; } int main() { int n, i, j, num; char tmp[M / 2]; cin >> n; while (n--) { memset(g, 0, sizeof(g)); cin >> r >> c; num = 1; gets(tmp); //在输入的r,c的后面还有空格,gets掉,题目的变态的地方,discuss里面有。 for (i = 0; i < c; i++) { gets(tmp); for (j = 0; j < r; j++) { if (tmp[j] == '#') map[i][j] = -1; else if (tmp[j] == ' ') map[i][j] = 0; else if (tmp[j] == 'A') map[i][j] = ++num; else if (tmp[j] == 'S') map[i][j] = 1; } } for (i = 0; i < c; i++) for (j = 0; j < r; j++) if (map[i][j] > 0) BFS(i, j); cout << Prim(1, num) << endl; } return 0; }