POJ 3026 Borg Maze(bfs+最小生成树-Prim)

Description
有一簇叫做Borg的外星生物,想要扫描整个迷宫建立与其所有下属的联系。迷宫有空格,代表能走的路,有#代表墙壁。有A代表生物,有S代表初始位置。从一个点出发,过程中可以随意分裂,但是行走方式只能是上下左右。然后我们要写一个程序,计算扫描的最短距离。也就是说,当有一个方式连接起来所有的点的时候(题中的A与S),计算这条线的最短距离
Input
第一行为用例组数,每组用例第一行为两个整数m和n表示迷宫的行列数,之后为一m*n矩阵,#代表墙壁,A代表生物,S代表初始位置
Output
对于每组用例,输出连接所有点的线的最短距离
Sample Input
这里写图片描述
Sample Output
8
11
Solution
最小生成树问题,先用bfs来遍历整张图,从一个点开始,往外扩张,遇到点就把当前扩张的次数记为从起始点到这个点的距离,建立每一个点到其他点的距离矩阵,图建完后直接套用prim的模板即可
Code

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
#define maxn 300
#define INF 1<<29
struct node
{
    int x,y;
};
int dx[4]={-1,0,0,1};
int dy[4]={0,-1,1,0};
char Map[maxn][maxn];//迷宫 
bool vis[maxn][maxn];//标记数组 
int num[maxn][maxn];//记录点的位置 
int cost[maxn][maxn];//记录两点权值 
int dis[maxn][maxn];//距离矩阵 
int T,n,m,res,ans;
void bfs(int sx,int sy)
{
    queue<node>P;
    memset(vis,0,sizeof(vis));//初始化 
    node temp;
    temp.x=sx;
    temp.y=sy;
    P.push(temp);//起点入队 
    vis[sx][sy]=true;//标记起点 
    dis[sx][sy]=0;//起点到起点距离为0 
    while(!P.empty())
    {
        node t=P.front();//出队 
        P.pop();
        int x=t.x,y=t.y;
        if(num[x][y]!=-1)//两点间权值为两点间距离 
            cost[num[sx][sy]][num[x][y]]=dis[x][y];
        for(int i=0;i<4;i++)//四个方向枚举 
        {
            int xx=x+dx[i],yy=y+dy[i];
            if(xx<0&&xx>=n&&yy<0&&yy>=m)//超出迷宫区域 
                continue;
            if(vis[xx][yy]||Map[xx][yy]=='#')//该处已被访问或者无法通过 
                continue;
            vis[xx][yy]=true;//可以走则将该步标记 
            dis[xx][yy]=dis[x][y]+1;//距离加一 
            node temp;
            temp.x=xx;
            temp.y=yy;
            P.push(temp);//入队 
        }
    }
}
int prim(int s)
{
    int d[110];//记录各点到顶点的最短距离 
    int ans=0;
    bool v[110];//标记数组 
    for(int i=0;i<res;i++)//初始化 
    {
        d[i]=cost[s][i];
        v[i]=false;
    }
    d[s]=0;//起点到起点最短距离为0 
    v[s]=true;//起点为第一个顶点 
    for(int i=0;i<res-1;i++)//prim算法 
    {
        int t,m=INF;
        for(int j=0;j<res;j++)//从不属于集合中的元素中找到距顶点权值最小的点 
            if(!v[j]&&m>=d[j])
                m=d[t=j];
        v[t]=true;//把该点加入集合中 
        ans+=m;//把边长加到结果中 
        for(int j=0;j<res;j++)//d[i]记录不属于集合中的元素距顶点的最小距离 
            if(!v[j]&&d[j]>cost[t][j])
                d[j]=cost[t][j];
    }
    return ans;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        char t[200];
        scanf("%d%d",&m,&n);
        gets(t);
        for(int i=0;i<n;i++)
            gets(Map[i]);
        res=0;
        memset(num,-1,sizeof(num));//初始化 
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                if(Map[i][j]=='S'||Map[i][j]=='A')//记录点的个数 
                    num[i][j]=res++;
                if(Map[i][j]=='S')
                    ans=res-1;
            }
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                if(Map[i][j]=='S'||Map[i][j]=='A')
                    bfs(i,j);
        printf("%d\n",prim(ans));//从起点开始建树 
    }
    return 0;
}

你可能感兴趣的:(POJ 3026 Borg Maze(bfs+最小生成树-Prim))