题意:给出一个二维字符串,里面有#代表不能走,' '空格代表可以走,然后还有'A'和'S'代表人,问从S到达所有'A'的最小通路,其中S点或者走到一个A点时可以分身。
思路:从其中每个人的位置开始深搜求出到其他点得距离。在这个图上求MST即为所求。
深搜的时候用一维保存位置,4个方向变成了+1,-1,+m,-m。此时需要注意+1和-1是否出现换行的情况。
#include <stdio.h>
#include <string.h>
#define clc(x,t) memset(x,t,sizeof(x));
#define N 105
#define INF 0x3fffffff
int m,n,T;
char s[N][N];
int q[N*N],hash[N*N],id[N*N],ori[4],used[N*N],step[N*N],g[N][N];
void init(){
clc(step,0);
clc(used,0);
}
int cd(int i,int j){
return i*m+j;
}
int test(int x){
int i = x/m;
int j = x%m;
return !used[x] && s[i][j]!='#' && x>=0 && x<m*n;
}
void bfs(int pos){
int i,rear,front,now,next;
init();
rear = front = -1;
q[++rear] = pos;
used[pos] = 1;
while(front < rear){
now = q[++front];
for(i = 0;i<4;i++){
if((i==0 && now%m==m-1) || (i==1 && now%m==0))//图方便用一维来表示位置需要注意这个
continue;
next = now+ori[i];
if(test(next)){
used[next] = 1;
q[++rear] = next;
step[next] = step[now]+1;
if(hash[next])
g[id[pos]][id[next]] = g[id[next]][id[pos]] = step[next];
}
}
}
}
int prim(int n){
int i,j,mm,pos,res=0;
memset(used, 0, sizeof(used));
for(i = 1;i<=n;i++)
id[i] = INF;
id[1] = 0;
for(i = 1;i<=n;i++){
mm = INF;
for(j = 1;j<=n;j++)
if(!used[j] && id[j]<mm){
pos = j;
mm = id[j];
}
used[pos] = 1;
res+=mm;
for(j = 1;j<=n;j++)
if(!used[j] && id[j]>g[pos][j])
id[j] = g[pos][j];
}
return res;
}
int main(){
scanf("%d",&T);
ori[0] = 1,ori[1] = -1;
while(T--){
int i,j,k;
char ch;
clc(hash,0);
clc(id,0);
scanf("%d %d",&m,&n);
while((ch=getchar())!='\n');
ori[2] = m,ori[3] = -m;
for(i = 0;i<n;i++)
gets(s[i]);
for(i = k = 0;i<n;i++)
for(j = 0;j<m;j++)
if(s[i][j]=='A' || s[i][j]=='S'){
hash[cd(i,j)] = 1;
id[cd(i,j)] = ++k;
}
for(i = 0;i<n*m;i++)
if(hash[i])
bfs(i);
printf("%d\n",prim(k));
}
return 0;
}