POJ 3026 Borg Maze (Prim)

来源:互联网 发布:火影忍者网络连接异常 编辑:程序博客网 时间:2024/06/06 18:40

题目大意

  • 给出m行n列的矩阵,所有元素均为’#’,’ ‘, ‘A’ ,’S’。其中#代表墙,即不可通过,’ ’ 则代表路。要求从S出发到达所有A的道路长度。

分析

  • 所有字母都作为结点,字母之间的距离作为边,构造图。
  • 首先用BFS找出每个节点到其他点的距离,从而得到边
  • 然后直接prim求解

代码

/* 所有字母都作为结点,字母之间的距离作为边,构造图 * 首先用BFS找出每个节点到其他点的距离,从而构造图 * 然后直接prim求解 */#include <iostream>#include <string>#include <cstring>#include <queue>#include <cstdio>using namespace std;#define INF 0x3fffffffconst int maxn = 55;int dir[4][2] = {{-1 , 0} , {1 , 0} , {0 , -1} , {0 , 1}};struct Pos {    int x , y , num;};int G[maxn*maxn][maxn*maxn];string str[maxn];int mp[maxn][maxn]; //映射,表示(i,j)处的字母在p中的编号Pos p[maxn*maxn];int bvis[maxn][maxn];//用BFS求出第k个到其它字母的最短距离void BFS(int k , int m , int n){    memset(bvis , 0 , sizeof(bvis));    queue<Pos> Q;    Q.push(p[k]);    bvis[p[k].x][p[k].y] = 1;    while(!Q.empty()) {        Pos cur = Q.front(); Q.pop();        for(int i = 0; i < 4; i++) {            int tx = cur.x + dir[i][0] , ty = cur.y + dir[i][1];            if(tx >= 0 && tx < m && ty >= 0 && ty < n && !bvis[tx][ty]) {                if(str[tx][ty] == '#') continue;                Q.push((Pos){tx , ty , cur.num+1});                bvis[tx][ty] = 1;                if(mp[tx][ty] != -1) {                    G[k][mp[tx][ty]] = cur.num + 1;                    //cout << mp[tx][ty] << endl;                }            }        }    }}int vis[maxn*maxn] , dis[maxn*maxn];int prim(int n , int s){    for(int i = 0; i < n; i++) {        dis[i] = G[s][i];        vis[i] = (i == s ? 1 : 0);    }    int rel = 0;    for(int i = 1; i < n; i++) {        int mi = INF , pos;        for(int j = 0; j < n; j++) if(!vis[j]) {            if(mi > dis[j]) {mi = dis[j]; pos = j;}        }        vis[pos] = 1; rel += mi;        for(int j = 0; j < n; j++) {            if(!vis[j] && dis[j] > G[pos][j]) dis[j] = G[pos][j];        }    }    return rel;}int main(){    int t , m , n;    cin >> t;    while(t--)    {        cin >> n >> m;        char tmp[100]; gets(tmp);        memset(mp , -1 , sizeof(mp));        for(int i = 0; i < m; i++) getline(cin , str[i]);        int cnt = 0 , s; //s是起点        for(int i = 0; i < m; i++) for(int j = 0; j < n; j++) {            if(str[i][j] != '#' && str[i][j] != ' ') {                p[cnt].x = i; p[cnt].y = j; p[cnt].num = 0;                mp[i][j] = cnt++;            }            if(str[i][j] == 'S') {s = cnt - 1;}        }        //求出每个字母到其他字母的距离,构建图        for(int i = 0; i < cnt; i++) BFS(i , m , n);        cout << prim(cnt,s) << endl;    }    return 0;}
0 0
原创粉丝点击