【POJ 3026】Borg Maze

来源:互联网 发布:安全第一网络银行 编辑:程序博客网 时间:2024/05/22 09:37

【POJ 3026】Borg Maze

一个考察队搜索alien 这个考察队可以无限分割 问搜索到所有alien所需要的总步数 即求一个无向图 包含所有的点并且总权值最小(最小生成树

BFS+最小生成树

Prim/Kruskal…懒死了 就这么贴吧……凑活看( ̄┰ ̄*)

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <queue>#include <algorithm>#define INF 0x3f3f3f3fusing namespace std;typedef struct Point{    int x,y;}Point;typedef struct Edge{    int u,v,w;    bool operator < (const struct Edge a)const    {        return w < a.w;    }}Edge;Edge eg[10100];bool vs[101][101];Point p[101];char mp[51][52];int id[51][51];int dis[101][101];bool vis[51][51];//int dss[101];//bool vs[101];int dirx[] = { 0, 0, 1,-1};int diry[] = { 1,-1, 0, 0};int ds[51][51];int tp,x,y,top;int pre[101];void Bfs(int xx,int yy){    memset(vis,0,sizeof(vis));    queue <pair<int,int> > q;    q.push(pair<int,int> (xx,yy));    vis[xx][yy] = 1;    ds[xx][yy] = 0;    int i,aa,bb,a,b;    while(!q.empty())    {        pair <int,int> pt = q.front();        q.pop();        a = pt.first;        b = pt.second;        for(i = 0; i < 4; ++i)        {            aa = a+dirx[i];            bb = b+diry[i];            if(aa > x || bb > y || aa < 1 || bb < 1 || mp[aa][bb] == '#' || vis[aa][bb]) continue;            ds[aa][bb] = ds[a][b]+1;            vis[aa][bb] = 1;            q.push(pair<int,int> (aa,bb));//            if(mp[aa][bb] != ' ') dis[id[xx][yy]][id[aa][bb]] = dis[id[aa][bb]][id[xx][yy]] = ds[aa][bb];            if(mp[aa][bb] != ' ' && !vs[id[xx][yy]][id[aa][bb]])            {                vs[id[xx][yy]][id[aa][bb]] = vs[id[aa][bb]][id[xx][yy]] = 1;                eg[top].u = id[xx][yy];                eg[top].v = id[aa][bb];                eg[top++].w = ds[aa][bb];            }        }    }}void Init(int n){    int i;    for(i = 0; i < n; ++i)        pre[i] = i;}int Find(int x){    if(x != pre[x]) pre[x] = Find(pre[x]);    return pre[x];}//int Prim()//{//    memset(vs,0,sizeof(vs));//    memset(dss,INF,sizeof(dss));//    dss[0] = 0;//    int i,j,p,w,sum = 0;//    for(i = 0; i < tp; ++i)//    {//        w = INF;//        for(j = 0; j < tp; ++j)//        {//            if(!vs[j] && w > dss[j])//            {//                w = dss[j];//                p = j;//            }//        }//        sum += w;//        vs[p] = 1;//        for(j = 0; j < tp; ++j)//        {//            if(!vs[j] && dss[j] > dis[p][j])//                dss[j] = dis[p][j];//        }//    }//    return sum;//}int main(){    int n,i,j;    int cnt,sum,k,r;    scanf("%d",&n);    while(n--)    {        memset(vs,0,sizeof(vs));        tp = top = 0;        scanf("%d %d",&y,&x);        gets(mp[0]);        for(i = 1; i <= x; ++i)        {            gets(mp[i]+1);            for(j = 1; mp[i][j]; ++j)            {                if(mp[i][j] != '#' && mp[i][j] != ' ')                {                    id[i][j] = tp;                    p[tp].x = i;                    p[tp++].y = j;                }            }        }        Init(tp);        for(i = 0; i < tp; ++i)        {            Bfs(p[i].x,p[i].y);        }//        printf("%d\n",Prim());        sort(eg,eg+top);        sum = cnt = 0;        for(i = 0; i < top; ++i)        {            k = Find(eg[i].u);            r = Find(eg[i].v);            if(k != r)            {                pre[k] = r;                sum += eg[i].w;                cnt++;            }            if(cnt == tp) break;        }        printf("%d\n",sum);    }    return 0;}
/*BFS+Prim*///Memory Time//368K   0MS#include<iostream>#include<string>#include <cstdlib>#include <cstdio>#include <cstring>using namespace std;const int inf=2501;      //无限大,最大迷宫的总长也就2500char map[51][51];  //迷宫原图int node[51][51];   //记录当前格是否为字母,是第几个字母int col,row;      //当前迷宫的行列数int num;         //字母顶点数数目int dist[102][102];      //构造结点图的两结点间权值,理论结点数最多为2500个(每一个允许通行的格为一个结点)                         //但是POJ的数据库允许压缩到101个,哈哈,这样时间和空间复杂度都减少很多int edge[102][102];      //构造字母图的两个字母间的边权,字母数最多为101class move{ public:    int row,col;}mov[4]={{0,-1},{0,1},{-1,0},{1,0}}; //分别对应 上 下 左 右void bfs(int i,int j){    bool vist[51][51];  //标记当前迷宫某一格是否已被访问    int que_x[2500],que_y[2500];  //坐标队列    int head=0,tail=0;  //队列指针    /*Initial*/    memset(dist,0,sizeof(dist));    memset(vist,false,sizeof(vist));    vist[i][j]=true;    que_x[tail]=i;    que_y[tail++]=j;    while(head<tail)    {        int x=que_x[head];        int y=que_y[head++];        if(node[x][y])            edge[ node[i][j] ][ node[x][y] ] = dist[x][y];   //抽取字母到字母的边权        for(int k=0;k<4;k++)        {            int mx=x+mov[k].row;            int my=y+mov[k].col;            if(mx>=1 && mx<= row && my>=1 && my<=col)                if(!vist[mx][my] && map[mx][my]!='#')                {                    que_x[tail]=mx;                    que_y[tail++]=my;                    vist[mx][my]=true;                    dist[mx][my]=dist[x][y]+1;                }        }    }    return;}int prim(void){    int s=1;    int m=1;    bool u[102];    u[s]=true;    int min_w;    int prim_w=0;    int point;    int low_dis[102];    for(int i=1;i<=num;i++)    {        low_dis[i]=inf;        u[i]=false;    }    while(true)    {        if(m==num)            break;        min_w=inf;        for(int i=2;i<=num;i++)        {            if(!u[i] && low_dis[i]>edge[s][i])                low_dis[i] = edge[s][i];            if(!u[i] && min_w>low_dis[i])            {                min_w=low_dis[i];                point=i;            }        }        s=point;        u[s]=true;        prim_w+=min_w;        m++;    }    return prim_w;}int main(int i,int j){    int test;    cin>>test;    while(test--)    {        /*Initial*/        memset(node,0,sizeof(node));        num=0;        /*Input*/        cin>>col>>row;        char temp[51];        gets(temp);  //吃掉cin遗留下来的换行符,我不知道为什么getchar()会AW        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]=++num;        }        /*BFS-> Structure Maps*/        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;}
0 0
原创粉丝点击