题意:给出一个二维字符串,里面有#代表不能走,' '空格代表可以走,然后还有'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; }