题目大意:让你求从S点到A点的所能达到的最小距离。
算法思路:先通过bfs求出各个字母之间的最短距离,再求最小生成树。
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define INF 0x3f3f3f3f
typedef struct Node
{
int x,y;
int lev;
int sym;
};
Node nodes[3000];
char a[300][300];
int edges[300][300];
int dist[3000];
int t;
int n,m,ssym,num,sum;
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
bool visited[300][300],visited2[3003];
int xb[300][300];
void bfs(Node node)
{
memset(visited,false,sizeof(visited));
queue<Node>que;
que.push(node);
visited[node.x][node.y]=true;
while(!que.empty())
{
Node cur=que.front();
que.pop();
for(int i=0;i<4;i++)
{
int nx=cur.x+dx[i];
int ny=cur.y+dy[i];
if(1<=nx&&nx<=n&&1<=ny&&ny<=m&&!visited[nx][ny]&&a[nx][ny]!='#')
{
if(a[nx][ny]=='A'||a[nx][ny]=='S')
{
edges[node.sym][nodes[xb[nx][ny]].sym]=cur.lev+1;
}
Node flag;
flag.x=nx;
flag.y=ny;
flag.lev=cur.lev+1;
visited[nx][ny]=true;
que.push(flag);
}
}
}
}
void prim()
{
sum=0;
int i,j;
memset(dist,0x3f,sizeof(dist));
memset(visited2,false,sizeof(visited2));
for(i=1;i<num;i++)
{
dist[i]=edges[1][i];
}
visited2[1]=true;
for(i=1;i<num;i++)
{
int MIN=INF,node=-1;
for(j=1;j<num;j++)
{
if(!visited2[j]&&dist[j]<MIN)
{
MIN=dist[j];
node=j;
}
}
if(node==-1)
return;
visited2[node]=true;
sum+=dist[node];
for(j=1;j<num;j++)
{
if(!visited2[j]&&dist[j]>edges[node][j])
{
dist[j]=edges[node][j];
}
}
}
}
int main()
{
scanf("%d",&t);
int i,j;
while(t--)
{
memset(nodes,0,sizeof(nodes));
memset(xb,0,sizeof(xb));
memset(edges,0,sizeof(edges));
num=1;
scanf("%d%d",&m,&n);
for(i=0;i<=n;i++)
{
gets(a[i]+1);
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(a[i][j]=='S')
{
Node node;
node.x=i;
node.y=j;
node.lev=0;
ssym=num;
node.sym=num;
xb[i][j]=num;
nodes[num++]=node;
}
else if(a[i][j]=='A')
{
Node node;
node.x=i;
node.y=j;
node.lev=0;
node.sym=num;
xb[i][j]=num;
nodes[num++]=node;
}
}
}
for(i=1;i<=num;i++)
{
bfs(nodes[i]);
}
prim();
printf("%d\n",sum);
}
}