//大概是说S要去消灭外星人,要找到最短的路把所有的外星人消灭。。就这样。。

//题意说的很复杂,大意就是求S到A的距离,因为S到A可分所以就像是求图的最小生成树,先用BFS求各点的距离,再用prim求最短距离。

#include<iostream>
#include<queue>
using namespace std;
int const inf=1000000;

struct node
{
 int x,y,stp;
};

int n,m,s,ans;
int dirt[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int map[105][105],v[105][105],newmap[105][105];

void bfs(int x1,int y1,int u,int num)//BFS
{
 queue <node> Q;
 node first,next;
 memset(v,0,sizeof(v));
 int i,j;
 first.x=x1;
 first.y=y1;
 first.stp=0;
 j=0;
 Q.push(first);
 v[first.x][first.y]=1;
 while(!Q.empty())
 {
  first=Q.front();
  Q.pop();
  for(i=0;i<4;i++)
  {
   next.x=first.x+dirt[i][0];
   next.y=first.y+dirt[i][1];
   next.stp=first.stp+1;
   if(next.x>=0&&next.x<n&&next.y>=0&&next.y<m&&map[next.x][next.y]!=-2&&v[next.x][next.y]==0)
   {
    if(map[next.x][next.y]>=0)
    {
     newmap[u][map[next.x][next.y]]=newmap[map[next.x][next.y]][u]=next.stp;
     j++;
     if(j==num)
      return;
    }
    v[next.x][next.y]=1;
    Q.push(next);
   }
  }
 }
}

void prim()//最小生成树
{
 int lowcost[105],adj[105];
 int i,j,k,min;
 for(i=0;i<s;i++)
 {
  lowcost[i]=newmap[0][i];
  adj[i]=0;
 }
 adj[0]=1;
 for(i=1;i<s;i++)
 {
  min=inf;
  for(j=1;j<s;j++)
  {
   if(adj[j]==0&&lowcost[j]<min)
   {
    min=lowcost[j];
    k=j;
   }
  }
  ans+=min;
  adj[k]=1;
  for(j=1;j<s;j++)
  {
   if(adj[j]==0&&lowcost[j]>newmap[k][j])
   {
    lowcost[j]=newmap[k][j];
   }
  }
 }
}

int main()
{
 int t,i,j,d,w;
 char c,str[105];
 cin>>t;
 while(t--)
 {
  cin>>m>>n;
  d=0;
  ans=0;
  c=getchar();//很恶心的题目,前面有空格,去掉。
  while(c==' ')
   c=getchar();
  for(i=0;i<n;i++)
  {
   gets(str);
   for(j=0;j<m;j++)
   {
    if(str[j]=='#') map[i][j]=-2;
    if(str[j]==' ') map[i][j]=-1;
    if(str[j]=='S') map[i][j]=0;
    if(str[j]=='A') map[i][j]=++d;
   }
  }
  w=d;
  s=d+1;
  for(i=0;i<n;i++)
   for(j=0;j<m;j++)
   {
    if(map[i][j]>=0)
    {
     bfs(i,j,map[i][j],w);
     map[i][j]=-1;
     w--;
    }
   }
   prim();
   cout<<ans<<endl;
 }
 return 0;
}

posted on 2011-08-12 21:36  →木头←  阅读(458)  评论(0编辑  收藏  举报