zoukankan      html  css  js  c++  java
  • 3026 Borg Maze BFS+prim

    /*

     

    题目:

       就是所在矩形中有一些外星人,一些人组队打怪去,可以分很多支队,问这些队一共所需的

       最少移动步数

     

    分析:

       由于可以分很多队,所以可以看做是从起点出发求最小生成树(其实有无起点一样,MST肯定

       包括起点),于是问题转换为求最小生成树。怎样处理点与点之间的距离。其实每两个点之间

       肯定存在通路,而任两点之间的最小直接距离可以通过bfs求到,于是可以通过枚举所有的点

       (即外星人和起点)到另外的点(还是外星人和起点)的距离。具体实现看代码

     

    */

    #include <iostream>

    #include <cstring>

    #include <cstdio>

    #include <queue>

    using namespace std;

    #define X 102

    int map[X][X],ma[X][X],dis[X],n,m,cnt;

    int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};//方向偏移量

    char ch[X][X];

    bool use[X][X],visit[X];

    struct node        //结构体,记录队列中的坐标和移动了的步数

    {

       int x,y,step;

    };

    bool check(int x,int y)//检查是否越界

    {

       if(x<0||y<0||x>=n||y>=m)

          return false;

       return true;

    }

    void bfs(int x,int y)

    {

       memset(use,false,sizeof(use));

       node cur;

       cur.x = x;

       cur.y = y;

       cur.step = 0;

       queue<node> q;     //入队

       q.push(cur);

       use[x][y] = true;

     

       int cx,cy,step;

       int px = x,py = y;

       while(!q.empty())

       {

          cur = q.front();   //队首出队

          q.pop();        //删除队首

     

          x = cur.x;

          y = cur.y;

          step = cur.step;

     

          if(ma[x][y]) //注意到图是无向图 ,ma数组记录的是该坐标下的目标图的顶点下标(从1开始)

             map[ ma[x][y] ][ ma[px][py] ] = map[ ma[px][py] ][ ma[x][y] ] = step;

          //map数组记录的是目标图中两顶点的距离

     

          for(int i=0;i<4;i++)

          {

             cx = x+dir[i][0];

             cy = y+dir[i][1];  //算出下一次到达的位置

             if(check(cx,cy)&&ch[cx][cy]!='#'&&!use[cx][cy])//没有越界,可走的,没走过的

             {

                use[cx][cy] = true;

                cur.x = cx;

                cur.y = cy;

                cur.step = step+1; //移动距离加一

                q.push(cur);    //入队

             }

          }

       }

    }

    void prim()        //求最小生成树,图为邻接矩阵map[][],prim标准模板

    {

       int ans = 0,k,MIN;

       memset(visit,false,sizeof(visit));

     

       for(int i=1;i<=cnt;i++)

          dis[i] = map[i][1];

       visit[1] = true;

       for(int i=1;i<cnt;i++)

       {

          MIN = 10000000;

          for(int j=1;j<=cnt;j++)

             if(!visit[j]&&dis[j]<MIN)

                MIN = dis[k=j];

          ans += MIN;

          visit[k] = true;

          for(int j=1;j<=cnt;j++)  //松弛操作

             if(!visit[j])

                dis[j] = min(dis[j],map[k][j]);

       }

       cout<<ans<<endl;

    }

    int main()

    {

       freopen("sum.in","r",stdin);

       freopen("sum.out","w",stdout);

       int t;

       cin>>t;

       while(t--)

       {

          cnt = 0;

          memset(ma,0,sizeof(ma));

          scanf("%d%d ",&m,&n);

          for(int i=0;i<n;i++)

          {

             gets(ch[i]);

             for(int j=0;j<m;j++)

                if(ch[i][j]=='A'||ch[i][j]=='S')

                    ma[i][j] = ++cnt;        //记录目标图的顶点

          }

          for(int i=0;i<n;i++)

             for(int j=0;j<m;j++)

                if(ma[i][j])    //若为外星人所在位置或者起点

                    bfs(i,j);

          prim();  //求最短路

       }

     

       return 0;

    }

  • 相关阅读:
    BZOJ 1013--[JSOI2008]球形空间产生器sphere(高斯消元)
    BZOJ 1012--[JSOI2008]最大数maxnumber(二分&单调栈)
    BZOJ 3357--[Usaco2004]等差数列(STL&DP)
    BZOJ 1011--[HNOI2008]遥远的行星(乱搞)
    BZOJ 1010--[HNOI2008]玩具装箱toy(斜率优化dp)
    BZOJ 5334--[Tjoi2018]数学计算(线段树)
    BZOJ 5395--[Ynoi2016]谁的梦(STL&容斥)
    BZOJ 1008--[HNOI2008]越狱(容斥&快速幂)
    一个典型的装饰器
    Nginx 配置文件详解
  • 原文地址:https://www.cnblogs.com/yejinru/p/2439675.html
Copyright © 2011-2022 走看看