想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:给出一个二维字符串,里面有#代表不能走,' '空格代表可以走,然后还有'A'和'S'代表人,问从S到达所有'A'的最小通路,就是最小生成树
解题思路:因为说了上面的A不会超过100个,所以开个102的数组够了,用BFS找出任意两点相距的最小距离保存在图中之后prim就可以了,前面看错题目以为x,y<=50就以为开个50的数组可以了,结果不断RE,后来开大才A了
/*
Memory 284K
Time 63MS
*/
#include <iostream>
#include <queue>
using namespace std;
#define MAXV 102
#define inf 1<<29
typedef struct{
int x,y;
}Point;
Point point[MAXV];
char s[MAXV][MAXV];
int m,n,psum,map[MAXV][MAXV];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
void findpoint(){
int i,j;
psum=1;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
if(s[i][j]=='A'){
point[psum].x=i;
point[psum++].y=j;
}else if(s[i][j]=='S'){
point[0].x=i;
point[0].y=j;
}
}
void bfs(int start){
int discover[MAXV][MAXV],dis[MAXV][MAXV];
queue <int> q;
int i,a,b,tx,ty;
for(i=0;i<m;i++)
for(int j=0;j<n;j++){
dis[i][j]=0;
discover[i][j]=0;
}
a=point[start].x;
b=point[start].y;
q.push(a);
q.push(b);
discover[a][b]=true;
while(!q.empty()){
a=q.front();q.pop();
b=q.front();q.pop();
for(i=0;i<4;i++){
tx=a+dx[i];
ty=b+dy[i];
if(!discover[tx][ty] && tx>=0 && tx<n && ty>=0 && ty<m && s[tx][ty]!='#'){
dis[tx][ty]=dis[a][b]+1;
discover[tx][ty]=true;
q.push(tx);
q.push(ty);
}
}
}
for(i=0;i<psum;i++){
int t=dis[point[i].x][point[i].y];
if(t) map[start][i]=t;
}
}
void prim(){
int i,j,v;
int d[MAXV],vis[MAXV];
for(i=0;i<psum;i++){
d[i]=map[0][i];
vis[i]=0;
}
for(i=0;i<psum;i++){
int min=inf;
for(j=0;j<psum;j++)
if(!vis[j] && d[j]<min){
min=d[j];
v=j;
}
vis[v]=1;
for(j=0;j<psum;j++){
if(!vis[j] && map[v][j]<d[j])
d[j]=map[v][j];
}
}
int ans=0;
for(i=0;i<psum;i++) ans+=d[i];
printf("%d\n",ans);
}
int main(){
int t,i;
scanf("%d\n",&t);
while(t--){
gets(s[0]);
sscanf(s[0],"%d%d",&n,&m);
for(i=0;i<m;i++) gets(s[i]);
findpoint(); //找到点的坐标
for(i=0;i<psum;i++) bfs(i); //计算距离
prim(); //最小生成树
}
return 0;
}