思路:转化为求S和所有A点的最小生成树。通过对每个A点和S点bfs建图,然后prim求MST。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
int move[4][2]={1,0,-1,0,0,1,0,-1};
int n, m, cnt, flag[55][55], vis[55][55], a[105][105], step[55][55], visited[105];
char maze[55][55];
struct node{int x, y;}p[105];
void init(){
char str[1005];
int i, j;
cnt=0;
gets(str);
sscanf(str, "%d%d", &m, &n);
memset(a, 0, sizeof(a));
for(i=0; i<n; i++){
gets(maze[i]);
for(j=0; j<m; j++){
if(maze[i][j]=='A'||maze[i][j]=='S'){
p[cnt].x=i;p[cnt].y=j;
flag[i][j]=cnt++;
}
}
}
}
bool check(node pt){
if(pt.x<0||pt.y<0|pt.x>=n||pt.y>=m||vis[pt.x][pt.y]||maze[pt.x][pt.y]=='#')
return true;
return false;
}
void bfs(int st){
int i;
queue<node> q;
q.push(p[st]);
node head, next;
memset(vis, 0, sizeof(vis));
memset(step, 0, sizeof(step));
step[p[st].x][p[st].y]=0;
vis[p[st].x][p[st].y]=1;
while(!q.empty()){
head=q.front();
q.pop();
for(i=0; i<4; i++){
next.x=head.x+move[i][0];
next.y=head.y+move[i][1];
if(check(next))continue;
step[next.x][next.y]=step[head.x][head.y]+1;
if(maze[next.x][next.y]=='A'||maze[next.x][next.y]=='S')
a[st][flag[next.x][next.y]]=step[next.x][next.y];
q.push(next);
vis[next.x][next.y]=1;
}
}
}
int prim(){
memset(visited, 0, sizeof(visited));
int i, j, d[105], f, tmp, ans=0;
visited[0]=1;
for(i=0; i<cnt; i++)
d[i]=a[0][i];
for(i=1; i<cnt; i++){
tmp=100000;
for(j=0; j<cnt; j++){
if(!visited[j]&&d[j]<tmp){
tmp=d[j];
f=j;
}
}
visited[f]=1;
ans+=tmp;
for(j=0; j<cnt; j++){
if(!visited[j]&&d[j]>a[f][j])
d[j]=a[f][j];
}
}
return ans;
}
void solve(){
for(int i=0; i<cnt; i++)
bfs(i);
printf("%d\n", prim());
}
int main(){
//freopen("1.txt", "r", stdin);
int T;
scanf("%d", &T);
getchar();
while(T--){
init();
solve();
}
return 0;
}