zoukankan      html  css  js  c++  java
  • POJ3026 Borg Maze(最小生成树)

    题目链接

    题目大意:

    任意两点(点表示字母)可以连线,求使所有点连通,且权值和最小。

    分析:

    第一感觉使3维的BFS。但写着写着,发现不对。

    应当用最小生成树解法。把每个字母(即A,或S)看成一个结点,如果求出来任意两个结点间的权值,则求解即为求最小生成树。

    通过暴力,对每一个字母进行BFS,求出任意两个结点的距离。然后prim.

    AC代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    
    using namespace std;
    
    const int maxn = 52;
    const int INF = (1<<29);
    
    int dx[] = {0, 0, -1, 1};
    int dy[] = {1, -1, 0, 0};
    
    struct Pos {
        int x, y;
    };
    
    char G[maxn][maxn];                                     //存放地图
    bool vis[maxn][maxn];                                   //深搜时用的标记数组
    int num[maxn][maxn], node[110][110];                    //num表示字母编号(从0开始),node字母间的最短距离
    int dis[maxn][maxn];                                    //深搜时用来记录到(sx,sy)的最短距离
    int n, m, cn;
    
    
    void BFS(int sx, int sy) {
        queue<Pos> Q;
    
        memset(vis, 0, sizeof(vis));
    
        Q.push((Pos){sx, sy});
        vis[sx][sy] = true;
        dis[sx][sy] = 0;
    
        while(!Q.empty()) {
            Pos e = Q.front(); Q.pop();
            int x = e.x, y = e.y;
    
            if(num[x][y] != -1)                              //(x,y)这点是字母
                node[num[sx][sy]][num[x][y]] = dis[x][y];
    
            for(int d=0; d<4; d++) {
                int nx = x+dx[d];
                int ny = y+dy[d];
    
                if(nx < 0 && ny < 0 && nx >= n && ny >= m) continue;
                if(vis[nx][ny] || G[nx][ny] == '#') continue;
    
                vis[nx][ny] = true;
                dis[nx][ny] = dis[x][y]+1;
                Q.push((Pos){nx, ny});
            }
        }
    }
    
    int prim(int s) {
        /*
         * cn为结点数,node为邻接矩阵
         * 任意两点间距离node[i][j]
         * 本题就是prim模板
         */
    
        int d[110], ans = 0;
        bool v[110];
    
        memset(v, false, sizeof(v));
    
        for(int i=0; i<cn; i++) {
            d[i] = node[s][i];
        }
    
        v[s] = true;
        d[s] = 0;
    
        for(int i=0; i<cn-1; i++) {
            int x, m=INF;
            for(int y=0; y<cn; y++) if(!v[y] && m >= d[y]) m = d[x=y];
            v[x] = true;
            ans += m;
            for(int y=0; y<cn; y++) if(!v[y] && d[y] > node[x][y]) d[y] = node[x][y];
        }
    
        return ans;
    }
    
    int main() {
        int T, n, m, ns;
        char tmp[200];
    
        scanf("%d", &T);
    
        while(T--) {
            scanf("%d%d", &m, &n);
            gets(tmp);                                      //discuss上说后面有多个空格
            for(int i=0; i<n; i++) {
                gets(G[i]);
            }
    
            cn = 0;                                         //字母的个数
            memset(num, -1, sizeof(num));
    
            for(int i=0; i<n; i++) {
                for(int j=0; j<m; j++) {
                    if(G[i][j] == 'S' || G[i][j] == 'A') {  //对字母进行编号
                        num[i][j] = cn++;
                    }
    
                    if(G[i][j] == 'S') {                    //'S'的编号
                        ns = cn-1;
                    }
                }
            }
    
            for(int i=0; i<n; i++) {
                for(int j=0; j<m; j++) {
                    if(G[i][j] == 'A' || G[i][j] == 'S')
                        BFS(i, j);
                }
            }
    
            printf("%d
    ", prim(ns));
        }
    
        return 0;
    }
  • 相关阅读:
    静态代码块--》非静态代码块--》构造方法
    谈谈SQL server的 worker threads-----微软亚太区数据库技术支持组 官方博客
    SQL SERVER SQLOS的任务调度--微软亚太区数据库技术支持组 官方博客
    线程池 数据库连接池 内存池
    SQL Server的thread scheduling(线程调度)
    ookla 网络上传下载 PING 测试
    mysql 监控工具
    SQL Server 2000 ——系统表和系统视图
    SQL Server 2000 ——DBCC命令
    几个未公开的 DBCC 命令
  • 原文地址:https://www.cnblogs.com/tanhehe/p/3253216.html
Copyright © 2011-2022 走看看