//poj 3026 Borg Maze //bfs+MST(广搜+最小生成树) //这题的英文实在看不懂,百度了别人的解题报告才知道意思的,所以要多多使用英语来慢慢提高才行 //这题的意思是要通过'S'去找'A',找到一个'A'就把它同化掉帮忙去同化别的'A' //其实就是最小生成树问题,只要用广搜求出每个点之间的距离后用prim就可以了 #include <stdio.h> #include <string.h> #include <queue> #define N 55 #define INF 1<<30 using namespace std; struct NODE { int x, y, step; //step record step when bfs(记录步数) }node[105]; //at most 100 aliens,in addition to start of the search(至少100个'A'再加一个'S') int line, row, cnt, ans; char map[N][N]; int mark[N][N], dis[105][105], dirx[4] = {0, 1, 0, -1}, diry[4] = {-1, 0, 1, 0}; //mark show the identifier of 'A' or 'S'(mark标记'A'和'S'的编号) //dis recode the distance between two node(dis标记两个结点间的距离) int dist[N]; //recorde the shortest distance when process prim(dist是在prim内记录最短距离的) bool vis[N][N], vist[N]; //vis is used in bfs, vist is used in prim(vis是bfs时用来标记是否遍历,vist是prim内结点是否遍历) void bfs(int index) { queue<NODE> que; memset(vis, false, sizeof(vis)); NODE now, next; node[index].step = 0; que.push(node[index]); vis[node[index].x][node[index].y] = true; while(!que.empty()) { now = que.front(); que.pop(); int x = now.x, y = now.y; for(int i = 0; i < 4; ++i) { int tx = x + dirx[i], ty = y +diry[i]; if(vis[tx][ty] == false && map[tx][ty] != '#') { next.x = x + dirx[i]; next.y = y + diry[i]; vis[next.x][next.y] = true; next.step = now.step + 1; que.push(next); if(map[next.x][next.y] == 'A' || map[next.x][next.y] == 'S') dis[ mark[ node[index].x ][ node[index].y ] ][ mark[next.x][next.y] ] = next.step; } } } } int prim() { for(int i = 0; i < cnt; ++i) { dist[i] = INF; vist[i] = false; } dist[0] = 0; while(1) { int min = INF, now = -1; for(int i = 0; i < cnt; ++i) { if(min > dist[i] && vist[i] == false) { min = dist[i]; now = i; } } if(now == -1) return ans; ans += min; vist[now] = true; for(int i = 0; i < cnt; ++i) if(vist[i] == false && dist[i] > dis[now][i]) dist[i] = dis[now][i]; } return ans; } int main() { int n_case; scanf("%d", &n_case); while(n_case--) { cnt = ans = 0; memset(mark, 0, sizeof(mark)); scanf("%d%d", &row, &line); char ch; while(ch = getchar(), ch != '\n'); for(int i = 0; i < line; ++i) { for(int j = 0; j < row; ++j) { map[i][j] = getchar(); if(map[i][j] == 'A' || map[i][j] == 'S') { mark[i][j] = cnt; node[cnt].x = i; node[cnt++].y = j; } } while(ch = getchar(), ch != '\n'); } for(int i = 0; i < cnt; ++i) bfs(i); //get shortest distance between any pair of charater besides '#' prim(); printf("%d\n", ans); } return 0; }