BFS+Prim.
其实A跟S都一样。。
用BFS求每个A(S)之间的最短距离,然后用Prim求答案就行了。
想到是MST就好做了。。
之前因为数组开小了,结果一直是TLE,查了一顿只发现了一些神奇的现象,囧。。
另外如果一直狂WA的话,可以参考一下POJ的discuss。。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <algorithm> #define MAXN 105 using namespace std; struct Point { int x,y,step; Point(int a=0,int b=0,int c=0):x(a),y(b),step(c) {} }; int dist[MAXN][MAXN]; int _id[MAXN][MAXN],N,n,m; char grid[MAXN][MAXN]= {0}; int M[5][2]= {{0,1},{0,-1},{1,0},{-1,0}}; void BFS(int x,int y) { Point st(x,y,0); queue<Point> q; q.push(st); int ID=_id[x][y]; bool vis[MAXN][MAXN]= {0}; memset(vis,0,sizeof(vis)); vis[x][y]=true; while(!q.empty()) { Point tmp=q.front(); q.pop(); for(int i=0; i<4; ++i) { int xx=tmp.x+M[i][0],yy=tmp.y+M[i][1],ss=tmp.step+1; if(xx<0||xx>m||yy<0||yy>n) continue; if(vis[xx][yy]) continue; else vis[xx][yy]=true; if(grid[xx][yy]=='#') continue; else { Point t(xx,yy,ss); q.push(t); if(grid[xx][yy]=='A') dist[ID][_id[xx][yy]]=ss; } } } } int main() { int T; scanf("%d",&T); getchar(); while(T--) { memset(dist,0,sizeof(dist)); memset(_id,0,sizeof(_id)); N=0; char str[MAXN]; gets(str); bool fir=false; n=-1; m=0; for(int i=0; str[i]; ++i ) { if(isdigit(str[i])) { if(n==-1) n=0; if(!fir) n=n*10+str[i]-'0'; else m=m*10+str[i]-'0'; } else { if(n!=-1) fir=true; } } for(int i=0; i<m; ++i) gets(grid[i]); int sx,sy; for(int i=0; i<m; ++i) { for(int j=0; j<n; ++j) if(grid[i][j]=='A') _id[i][j]=N++; else if(grid[i][j]=='S') { _id[i][j]=N++; sx=i; sy=j; grid[i][j]='A'; } } for(int i=0; i<m; ++i) for(int j=0; j<n; ++j) if(grid[i][j]=='A') BFS(i,j); int mincost[MAXN],ans=0; bool used[MAXN]; memset(mincost,0x7f,sizeof(mincost)); memset(used,0,sizeof(used)); mincost[0]=0; while(1) { int v=-1; for(int i=0; i<N; ++i) if(!used[i]&&(v==-1||(mincost[i]<mincost[v]))) v=i; if(v==-1) break; used[v]=true; ans+=mincost[v]; for(int j=0; j<N; ++j) mincost[j]=min(mincost[j],dist[v][j]); } printf("%d\n",ans); } return 0; }