POJ 3026 Borg Maze(Prim+bfs求各点间距离)

题目链接:http://poj.org/problem?id=3026

题目大意:在一个y行 x列的迷宫中,有可行走的通路空格’  ‘,不可行走的墙’#’,还有两种英文字母A和S,现在从S出发,要求用最短的路径L连接所有字母,输出这条路径L的总长度。

解题思路:相当于所有的字母A和S都是结点,求连接这些结点的最小距离和,是最小生成树的题目。先用BFS求各点间的距离,然后再用Prim(Kruskal也可以)求出最小距离就可以了。

     注意:输完行列m和n之后,后面有一堆空格,要用gets()去掉,题目有问题,超级坑。

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<queue>
  5 #include<algorithm>
  6 using namespace std; 
  7 const int N=1e2+5;
  8 const int MAXN=1e2+5;
  9 const int INF=0x3f3f3f3f;
 10 
 11 int n,m;
 12 int d[4][2]={0,1,0,-1,-1,0,1,0};
 13 int num[N][N],cost[N][N],root[MAXN],low[MAXN];
 14 bool vis[N][N],used[MAXN];
 15 char str[N][N];
 16 
 17 struct node{
 18     int x,y,step;
 19     node(){}
 20     node(int x,int y,int step){
 21         this->x=x;
 22         this->y=y;
 23         this->step=step;
 24     }
 25 }pre;
 26 
 27 //(x,y)点到各个点之间的最短距离 
 28 void bfs(int x,int y){
 29     memset(vis,false,sizeof(vis));
 30     queue<node>q;
 31     q.push(node(x,y,0));
 32     vis[x][y]=true;
 33     while(!q.empty()){
 34         pre=q.front();
 35         q.pop();
 36         for(int i=0;i<4;i++){
 37             int xx=pre.x+d[i][0];
 38             int yy=pre.y+d[i][1];
 39             int t=pre.step+1;
 40             if(x<=0||y<=0||x>n||y>m||vis[xx][yy]||str[xx][yy]=='#')
 41                 continue;
 42             if(str[xx][yy]=='S'||str[xx][yy]=='A')
 43                 cost[num[x][y]][num[xx][yy]]=t;
 44             vis[xx][yy]=true;
 45             q.push(node(xx,yy,t));
 46         }
 47     }
 48 }
 49 //Prim求最小生成树 
 50 int Prim(int cnt){
 51     memset(used,false,sizeof(used));
 52     for(int i=1;i<=cnt;i++){
 53         low[i]=cost[1][i];
 54     }
 55     used[1]=true;
 56     int ans=0;
 57     for(int i=1;i<cnt;i++){
 58         int k=-1;
 59         for(int j=1;j<=cnt;j++){
 60             if(!used[j]&&(k==-1||low[k]>low[j])){
 61                 k=j;
 62             }
 63         }
 64         if(k==-1||low[k]==INF) return -1;
 65         ans+=low[k];
 66         used[k]=true;
 67         for(int j=1;j<=cnt;j++){
 68             if(!used[j]&&low[j]>cost[k][j])
 69                 low[j]=cost[k][j];
 70         }
 71     }
 72     return ans;
 73 }
 74 
 75 int main(){
 76     int t;
 77     char tmp[105];
 78     scanf("%d",&t);
 79     while(t--){
 80         memset(cost,0x3f,sizeof(cost));
 81         scanf("%d%d",&m,&n);
 82         //注意行列后面有一大堆空格要用gets(),出题人怕是个智。。。 
 83         gets(tmp);
 84         int cnt=0;
 85         for(int i=1;i<=n;i++){
 86             gets(str[i]+1);
 87             for(int j=1;j<=m;j++){
 88                 if(str[i][j]=='S'||str[i][j]=='A')
 89                     num[i][j]=++cnt;
 90             }
 91         }
 92         for(int i=1;i<=n;i++){
 93             for(int j=1;j<=m;j++){
 94                 if(str[i][j]=='S'||str[i][j]=='A'){
 95                     bfs(i,j);
 96                 }
 97             }
 98         }
 99         printf("%d
",Prim(cnt));
100     }
101     return 0;
102 }
原文地址:https://www.cnblogs.com/fu3638/p/7901173.html