poj3026 Borg Maze (bfs+prim最小生成树)(有巨坑)

poj3026

问题描述(机翻):

博格人是来自银河系德尔塔象限的强大的增强类人种族。博格集体是用来描述博格文明群体意识的术语。博格人的每一个个体都通过一个复杂的子空间网络与集体联系在一起,以确保每个成员都能得到持续的监督和指导。
你的任务是帮助博格人(是的,真的),通过开发一个程序,帮助博格人估算出扫描迷宫的最低成本,通过移动北、西、东、南的台阶来同化隐藏在迷宫中的外星人。棘手的是,搜索的开始是由100多个个体组成的大群体进行的。每当一个外星人被同化,或者在搜索开始时,这个群体可能会分裂成两个或更多的群体(但他们的意识仍然是集体的)。一个迷宫的搜索成本被定义为所有参与搜索的组所走的总距离。也就是说,如果原组走5步,然后分成两组,每组走3步,总距离为11=5+3+3。

输入

在输入的第一行有一个整数N <= 50,给出了输入中测试用例的数量。每个测试用例都以一行开始,其中包含两个整数x,y,比如1 <= x,y <= 50。之后是y行,每一行x个字符。对于每个字符,空格’’ "代表一个开放的空间,散列符号’’ # "代表一堵堵墙,大写字母’’ a "代表外星人,大写字母’’ S "代表搜索的开始。迷宫的外围总是封闭的,即,没有办法从“S”的坐标中跳出来。迷宫中最多有100个外星人,每个人都可以找到。

输出

对于每个测试用例,输出一行代码,其中包含成功搜索迷宫的最小成本,不留下任何外星人。

分析:

先给每个点bfs求出当前点到其他点的距离并记录。
然后prim求最小生成树就行了。
我开始是用的结构体存坐标。一直wa到看别人代码改,最后在一篇博客里面看到说开始的数字输入的后面不止一个空格,getchar()无限wa,巨坑。(可恶啊)。

代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<string>
#include<algorithm>
#include<sstream>
#include<memory>
#include<utility>
#include<functional>
#include<iterator>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=105;
int n,m;
int all;
string s[maxm];
int name[maxm][maxm];
int g[maxm][maxm];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
queue<pair<int,int> >q;
void bfs(int xx,int yy){
    while(!q.empty())q.pop();
    q.push(make_pair(xx,yy));
    int time[maxm][maxm];
    memset(time,-1,sizeof time);
    time[xx][yy]=0;
    while(!q.empty()){
        pair<int,int>a=q.front();
        q.pop();
        if(name[a.first][a.second]!=0){
            g[name[xx][yy]][name[a.first][a.second]]=time[a.first][a.second];
        }
        for(int i=0;i<4;i++){
            int aa=a.first+dir[i][0];
            int bb=a.second+dir[i][1];
            if(aa<0||aa>=n||bb<0||bb>=m)continue;
            if(s[aa][bb]=='#'){
                continue;
            }
            if(time[aa][bb]!=-1){
                continue;
            }
            time[aa][bb]=time[a.first][a.second]+1;
            q.push(make_pair(aa,bb));
        }
    }
}
void prim(){
    int ans=0;
    int vis[maxm]={0};
    int d[maxm];
    for(int i=1;i<=all;i++){
        g[i][i]=0;
        d[i]=g[1][i];
    }
    vis[1]=1;
    for(int k=1;k<=all-1;k++){
        int t=-1;
        for(int i=1;i<=all;i++){
            if(!vis[i]){
                if(t==-1||d[t]>d[i]){
                    t=i;
                }
            }
        }
        vis[t]=1;
        ans+=d[t];
        for(int i=1;i<=all;i++){
            if(!vis[i]){
                d[i]=min(d[i],g[i][t]);
            }
        }
    }
    cout<<ans<<endl;
}
int main(){
    int T;
    cin>>T;
    while(T--){
        cin>>m>>n;
        getline(cin,s[0]);//这个地方不止一个空格,所有getchar()去空格的话会无限wa。我佛了
        //init
        all=0;
        memset(name,0,sizeof name);
        memset(g,inf,sizeof g);
        //
        for(int i=0;i<n;i++){
            getline(cin,s[i]);
            for(int j=0;j<m;j++){
                if(s[i][j]=='A'||s[i][j]=='S'){
                    name[i][j]=++all;
                }
            }
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(name[i][j]){
                    bfs(i,j);
                }
            }
        }
        prim();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值