题目链接:http://poj.org/problem?id=3026
题目大意:
在一个y行 x列的迷宫中,有可行走的通路空格’ ‘,不可行走的墙’#’,还有两种英文字母A和S,现在从S出发,要求用最短的路径连接所有字母,输出这条路径的总长度。一个格子的长度为1;
思路:
记录途中每个字母的位置,利用搜索求出字母两两之间的距离,构造出图,再求最小生成树;
/*BFS + Prim*/
#include<iostream>
#include<string.h>
using namespace std;
const int inf=1<<26;
int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
int n;
int graph[102][102];
int low_w[51];
bool visit[51];
int row,col;
int dist[102][102];
int node[51][51];
char map[51][51];
void bfs(int i,int j)
{
int queue_x[3000];
int queue_y[3000];
int head=0;
int tail=0;
bool vis[51][51];
memset(vis,false,sizeof(vis));
memset(dist,0,sizeof(dist));
queue_x[tail]=i;
queue_y[tail++]=j;
while(head<tail)
{
int x=queue_x[head];
int y=queue_y[head++];
if(node[x][y])
graph[ node[i][j] ][ node[x][y] ]= dist[x][y];
for(int k=0;k<4;k++)
{
int mx=x+dir[k][0];
int my=y+dir[k][1];
if(mx>=1 && mx<= row && my>=1 && my<=col)
{
if(!vis[mx][my] && map[mx][my]!='#')
{
queue_x[tail]=mx;
queue_y[tail++]=my;
vis[mx][my]=true;
dist[mx][my]=dist[x][y]+1;
}
}
}
}
return ;
}
int prim()
{
int i,j;
int prim_w=0;
int min_w;
int pos_flag;
for(i=1;i<=n;i++)
{
low_w[i]=graph[1][i];
visit[i]=false;
}
visit[1]=true;
for(i=1;i<n;i++)
{
min_w=inf;
for(j=1;j<=n;j++)
{
if(!visit[j] && min_w>low_w[j])
{
min_w=low_w[j];
pos_flag=j;
}
}
prim_w += min_w;
visit[pos_flag]=true;
for(j=1;j<=n;j++)
{
if(!visit[j] && low_w[j]>graph[pos_flag][j])
low_w[j]=graph[pos_flag][j];
}
}
return prim_w;
}
int main(int i,int j)
{
int cases;
cin>>cases;
while(cases--)
{
char str[100];
cin>>col>>row;
gets(str);
memset(node,0,sizeof(node));
n=0;
for(i=1;i<=row;i++)
{
gets(map[i]);
for(j=1;j<=col;j++)
{
if(map[i][j]=='A'||map[i][j]=='S')
node[i][j]=++n;
}
}
/*BFS-> Structure Graph*/
for(i=1;i<=row;i++)
{
for(j=1;j<=col;j++)
{
if(node[i][j])
bfs(i,j);//构造结点i,j到其他所有结点的边权(非#的格子就是一个结点)
}
}
/*Prim Algorithm & Output*/
cout<<prim()<<endl;
}
return 0;
}