POJ 3026 Borg Maze (BFS+Prim)

来源:互联网 发布:淘宝大学vip课程可靠吗 编辑:程序博客网 时间:2024/06/09 23:38

题意:

给一个x*y的网格,x,y<50,要遍历其中的N个点(N<100),重复走过的路不算,问最短多长。


分析:

由于重复走过的路不算所以可以用最小生成树。

然后该题又是基于网格求两点最近距离,用BFS预处理出每个点到其他点的最短距离,注意这里处理要把A和S还有空格都看做可以走的地方都要处理,

这里的距离数组用dis[i][j]表示到这一次定的基准点的最短距离,用到方向数组(我当时傻逼了,把方向数组的第二个维度开成4了。。。)

处理完后要更新最后在Prim里的距离。


总结:

手残的地方见代码部分吧。

这一题有坑。。。要gets()


#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<iostream>using namespace std;const int Pmaxn=105;const int Nmaxn=55;int dir[4][2]={-1,0,0,1,1,0,0,-1}; //第二个维度是2!!!int map[Nmaxn][Nmaxn];int dis[Nmaxn][Nmaxn]; //距离,这里的横纵坐标就是网格里面的横纵坐标,因为每一次都是和基准点的距离不代表点和点的距离,开大了memset会Tint v[Nmaxn][Nmaxn];   // map上是否访问过int ans[Pmaxn][Pmaxn];char p[Nmaxn];int x,y; //x-行 y-列int t;int cnt;struct ali{    int x,y;}A[Pmaxn];int st;queue<ali> q;void bfs(int start){    q.push(A[start]);    /*for(int i=0;i<=x+1;i++)    {        for(int j=0;j<=y+1;j++)        {            v[i][j]=0;            dis[i][j]=0;        }    }*/    memset(dis,0,sizeof(dis));    memset(v,0,sizeof(v));    v[A[start].x][A[start].y]=1;//第一个标记入队的点    while(!q.empty())    {        ali top=q.front();        q.pop();        for(int i=0;i<4;i++)        {            int tx,ty;            tx=top.x+dir[i][0];            ty=top.y+dir[i][1];            if(map[tx][ty]!=1 && !v[tx][ty])            {                dis[tx][ty]=dis[top.x][top.y]+1;                v[tx][ty]=1;                ali newer;                newer.x=tx;                newer.y=ty;                q.push(newer);            }        }    }    for(int i=1;i<cnt;i++)    {       if(dis[A[i].x][A[i].y])//因为这一题保证了每一个点都会到达,但是如果有的点不能到达,因为之前初始化是距离0,这里加判断看能不能到达,不能就是inf       {           ans[start][i]=dis[A[i].x][A[i].y];       }    }    ans[start][start]=0;}const int inf=0x3f3f3f3f;int lowcost[Pmaxn],closest[Pmaxn];int res=0;void prim(int s){    int midis,mione;    int i,j;    res=0;    for(i=1;i<cnt;i++)    {        lowcost[i]=ans[s][i];        closest[i]=s;    }    //cout<<" cnt= "<<cnt<<endl;    for(i=1;i<cnt;i++)    {        midis=inf;        for(j=1;j<cnt;j++)        {            if(lowcost[j]&&midis>lowcost[j])            {                midis=lowcost[j];                mione=j;            }        }//minone的处理是在一轮循环后找到最大值才定,这里括号加错了。。。找了好久。            res+=lowcost[mione];            //cout<<A[mione].x<<" "<<A[mione].y<<" "<<lowcost[mione]<<endl;            lowcost[mione]=0;//表示已经加入树        for(j=1;j<cnt;j++)        {            if(lowcost[j]>ans[j][mione] && lowcost[j])            {                lowcost[j]=ans[j][mione];                closest[j]=mione;            }        }    }}int main(){    //freopen("in","r",stdin);    scanf("%d",&t);    while(t--)    {        scanf("%d %d",&y,&x);        int i,j;        cnt=1;        memset(ans,0x3f,sizeof(ans));        for(i=0;i<=x+1;i++)            map[i][0]=map[i][y+1]=1;        for(i=0;i<=y+1;i++)            map[0][i]=map[x+1][i]=1;        gets(p);//cout<<p;        for(i=1;i<=x;i++)        {            gets(p);//cout<<p;            for(j=1;j<=y;j++)            {                if(p[j-1]=='S' || p[j-1]=='A')//这里的j要-1                {                    if(p[j-1]=='S') st=cnt;                    map[i][j]=2;                    A[cnt].x=i;                    A[cnt].y=j;                    cnt++;                }                else if(p[j-1]==' ')                    map[i][j]=0;                else if(p[j-1]=='#')                    map[i][j]=1;                    //printf("map[%d][%d]=%d \n",i,j,map[i][j]);            }            //cout<<endl;        }       /*for(i=0;i<=x+1;i++)        {            for(j=0;j<=y+1;j++)              cout<<map[i][j];              cout<<endl;        }*/        for(i=1;i<cnt;i++)        {            //cout<<i<<endl;            bfs(i);        }        /*for(i=1;i<cnt;i++)        {            for(j=1;j<cnt;j++)              cout<<A[i].x<<" "<<A[i].y<<" "<<A[j].x<<" "<<A[j].y<<" "<<ans[i][j]<<endl;              cout<<endl;        }*/        prim(st);//第一次非常神奇的我居然没有调用这个函数。。。Orz        printf("%d\n",res);    }return 0;}


0 0