poj 3026 Borg Maze (bfs+prim)

题意:在迷宫中找存在的外星人A撒。。开始是一个组织找,后来这个组织可以分裂成

            很多组。求找到所有外星人的最小步数。(分裂后,步数计算为所有组织的步数和)


思路:因为要保证每个外星人A都找到,加上组织所在起始点S,求最小步数。即求图中

           n个点的最小生成树(n=外星人的个数+1)。

            bfs找每两点间的距离。


1、这题要注意时间复杂度。

开始预处理时把所有外星人和组织起点横纵坐标记录后。用了两个for循环,来找每两点的

距离。这样要调用n*n次bfs去搜状态,结果tle。其实每次重复搜没必要。


将n*n复杂度可以降到n。也就是遍历n个点,以其中每个点作起点一次,来搜到达其他各点

的最短距离。


2、这题要注意数组大小

外星人最多100,加上组织起点S一共101个点。

数组开小就wa了。


3、这题读入迷宫行列后不能用getchar,因为后面不止是单纯的回车。还有多余空格。

要用gets()吃掉所有。


代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;

struct node
{
    int x,y;
    int step;
};
char m[55][55];
int r[110],c[110],ans,rear,x,y;
int edge[110][110],dis[110];
bool vis[110];
bool v[55][55];
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
queue<node> Q;

void dist(int i)
{
    while(!Q.empty())
        Q.pop();
    node a,b,tmp;
    int num=0;

    a.x=r[i],a.y=c[i];
    a.step=0;
    Q.push(a);
    v[r[i]][c[i]]=1;
    while(!Q.empty())
    {
        tmp=Q.front();
        Q.pop();
        for(int k=0;k<rear;k++)
        {
            if(tmp.x==r[k] && tmp.y==c[k])
            {
                edge[k][i]=edge[i][k]=tmp.step;
                num++;
                break;
            }
        }
        if(num==rear)
            break;
        for(int k=0;k<4;k++)
        {
            b.x=tmp.x+dx[k];
            b.y=tmp.y+dy[k];
            b.step = tmp.step+1;
            if(b.x>=1 && b.x<=y && b.y>=1&&b.y<=x && m[b.x][b.y]!='#'&& !v[b.x][b.y])
            {
                v[b.x][b.y]=1;
                Q.push(b);
            }
        }
    }
}

void prim()
{
    int u=0;
    for(int i=1;i<rear;i++)
    {
        dis[i]=edge[u][i];
    }
    vis[u]=1;
    for(int i=1;i<rear;i++)
    {
        int minc = INF;
        for(int j=0;j<rear;j++)
        {
            if(!vis[j] && dis[j]<minc)
            {
                u=j;
                minc=dis[j];
            }
        }
        ans+=minc;
        vis[u]=1;
        for(int j=0;j<rear;j++)
        {
            if(!vis[j] && edge[u][j]<dis[j])
                dis[j]=edge[u][j];
        }
    }
}
int main()
{
    int T,sx,sy;
    char shit[50];
    scanf("%d",&T);
    while(T--)
    {
        memset(vis,0,sizeof(vis));

        scanf("%d%d",&x,&y);
        gets(shit);
        for(int i=1;i<=y;i++)
            gets(m[i]+1);

        rear=0;
        for(int i=1;i<=y;i++)
        {
            for(int j=1;j<=x;j++)
            {
                if(m[i][j]=='S')
                {
                    sx=i;
                    sy=j;
                }
                else if(m[i][j]=='A')
                {
                    r[rear]=i;
                    c[rear++]=j;
                }
            }
        }
        r[rear]=sx;
        c[rear++]=sy;
        for(int i=0;i<rear;i++)
        {
            memset(v,0,sizeof(v));
            dist(i);
        }
        ans=0;
        prim();
        printf("%d\n",ans);
    }
    return 0;
}



             

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值