Borg Maze

poj3026:http://poj.org/problem?id=3026

题意:在一个y行 x列的迷宫中,有可行走的通路空格’ ‘,不可行走的墙’#’,还有两种英文字母A和S,现在从S出发,要求用最短的路径L连接所有字母,输出这条路径L的总长度。
题解:一格的长度为1,而且移动的方法只有上、下、左、右,所以在无任何墙的情况下(根据题意的“分离”规则,重复走过的路不再计算因此当使用prim算法求L的长度时,根据算法的特征恰好不用考虑这个问题(源点合并很好地解决了这个问题),L就是最少生成树的总权值W由于使用prim算法求在最小生成树,因此无论哪个点做起点都是一样的,(通常选取第一个点),因此起点不是S也没有关系所以所有的A和S都可以一视同仁,看成一模一样的顶点就可以了剩下的问题关键就是处理 任意两字母间的最短距离,由于存在了“墙#” ,这个距离不可能单纯地利用坐标加减去计算,必须额外考虑,推荐用BFS(广搜、宽搜),这是本题的唯一难点,因为prim根本直接套用就可以了。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<algorithm>s
  5 #include<queue>
  6 #include<string>
  7 #define INF 10000000
  8 using namespace std;
  9 int xn,yn,top,pos;
 10 int n,m;
 11 char map[56][56];
 12 int dist[56][56],lowcost[2505],g[2504][2506],visit[56][56];
 13 struct Node{
 14     int x;
 15     int y;
 16     int step;
 17 };
 18 struct Node1{
 19     int x;
 20     int y;
 21 }node[2503];
 22 void init(){
 23     for(int i=1;i<=xn;i++)
 24       for(int j=1;j<=yn;j++)
 25         dist[i][j]=INF;
 26   memset(visit,0,sizeof(visit));        
 27 }
 28 void bfs(Node1 a){
 29     init();
 30     dist[a.x][a.y]=0;
 31     queue<Node>Q;
 32     Node temp;
 33     temp.x=a.x;
 34     temp.y=a.y;
 35     temp.step=0;
 36     visit[a.x][a.y]=true;
 37     Q.push(temp);
 38     while(!Q.empty()){
 39         Node tmp=Q.front();
 40         Q.pop();
 41         int x=tmp.x;
 42         int y=tmp.y;
 43     if(x>=2&&map[x-1][y]!='#'&&!visit[x-1][y]){
 44             visit[x-1][y]=true;//bfs收索时候,一定要在入队之前标记,如果在出队 
 45                dist[x-1][y]=tmp.step+1;//时在标记,会使得一个元素在队列中可能会被加入多次。
 46               temp.x=x-1;
 47               temp.y=y;
 48               temp.step=tmp.step+1;
 49               Q.push(temp);
 50                 }
 51         if(x<xn&&map[x+1][y]!='#'&&!visit[x+1][y]){
 52                visit[x+1][y]=true;
 53                dist[x+1][y]=tmp.step+1;
 54               temp.x=x+1;
 55               temp.y=y;
 56               temp.step=tmp.step+1;
 57               Q.push(temp);
 58             }
 59         if(y>=2&&map[x][y-1]!='#'&&!visit[x][y-1]){
 60                visit[x][y-1]=true;
 61                 dist[x][y-1]=tmp.step+1;
 62               temp.x=x;
 63               temp.y=y-1;
 64               temp.step=tmp.step+1;
 65               Q.push(temp);
 66            }
 67         if(y<yn&&map[x][y+1]!='#'&&!visit[x][y+1]){
 68               visit[x][y+1]=true;
 69                dist[x][y+1]=tmp.step+1;
 70               temp.x=x;
 71               temp.y=y+1;
 72               temp.step=tmp.step+1;
 73               Q.push(temp);
 74            }
 75     }
 76 }
 77 void prim(int v0){
 78     int sum=0;
 79     for(int i=1;i<top;i++){
 80         lowcost[i]=g[v0][i];
 81     }
 82     lowcost[v0]=-1;
 83     for(int i=1;i<top-1;i++){
 84         int min=INF;
 85         int v=-1;
 86         for(int j=1;j<top;j++){
 87             if(lowcost[j]<min&&lowcost[j]!=-1){
 88                 min=lowcost[j];
 89                 v=j;
 90             }
 91         }
 92         if(v!=-1){
 93             sum+=lowcost[v];
 94             lowcost[v]=-1;
 95             for(int k=1;k<top;k++)
 96              if(lowcost[k]!=-1&&g[v][k]<lowcost[k])
 97                  lowcost[k]=g[v][k];
 98         }
 99     }
100     printf("%d
",sum);
101 }
102 int main(){
103     int cas;string line;
104     scanf("%d",&cas);
105     char sss[30];
106     while(cas--){
107         top=1;
108         scanf("%d%d",&yn,&xn);
109         gets(sss);//这里如果用gethchar()oj会判wa 
110         for(int i=1;i<=xn;i++){
111             getline(cin,line);//读取一整行 
112             
113            for(int j=1;j<=yn;j++){  
114               map[i][j]=line[j-1];
115              if(map[i][j]!=' '&&map[i][j]!='#'){//记录每个A和S 
116                    node[top].x=i;
117                    node[top++].y=j;
118                    }
119              if(map[i][j]=='S'){//记录起点 
120                      pos=top-1;
121                }
122              }
123          }
124          for(int i=1;i<top;i++){ 
125               bfs(node[i]);//一遍bfs找出了所有其他点与改点的距离 
126              for(int j=i+1;j<top;j++){//建边 
127                g[i][j]=g[j][i]=dist[node[j].x][node[j].y];
128              }
129          }
130         for(int i=1;i<top;i++)//初始化 
131           for(int j=1;j<top;j++){
132               if(i==j)g[i][j]=0;
133               else if(g[i][j]==0)g[i][j]=INF;
134           }
135           prim(pos);     
136      }
137 }
View Code

原文地址:https://www.cnblogs.com/chujian123/p/3377822.html