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;
}