poj 3026 Borg Maze(java bfs + prim)

来源:互联网 发布:广州seo顾问 编辑:程序博客网 时间:2024/06/14 12:28
package prim;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

/**问题请参考http://poj.org/problem?id=3026
 * @author rayli

 * @date:2014-7-28 下午4:07:33
 * 题意 :给定一个迷宫,在一个迷宫内,建立一颗最小生成树连接所有点
 *通过BFS找到'S'与每个’A'之间的最短路径。然后prim 建立最小生成树。
 *
 *求 任意两字母间的最短距离 时不能直接用BFS求,

1、必须先把矩阵中每一个允许通行的格看做一个结点(就是在矩阵内所有非#的格都作为图M的一个顶点),
对每一个结点i,分别用BFS求出它到其他所有结点的权值(包括其本身,为0),构造结点图M;

2、然后再加一个判断条件,从图M中抽取以字母为顶点的图,进而构造字母图N

这个判定条件就是当结点图M中的某点j为字母时,把i到j的权值再复制(不是抽离)出来,记录到字母图N的邻接矩阵中

3、剩下的就是对字母图N求最小生成树了
 */

class Node
{//结点
   public int x;//x坐标
   public int y;//y坐标
//   public int w;
}

public class BorgMaze
{
    static char map[][];
    static Node node[];
    static int r;
    static int c;
    static int num;
    int ans;
    static int cost[][];
    
    void bfs(Node n)
    {
        int dir[][] = {{0,1}, {0,-1}, {1,0}, {-1, 0}};//方向
        int t[][] = new int[r][c];
        
        //对t进行初始化为-1
        for(int i=0; i<r; i++)
            for(int j=0; j<c; j++)
                t[i][j] = -1;
        
        Queue<Node> q = new LinkedList<Node>();
        t[n.x][n.y] = 0;//对开始点进行标记
        q.add(n);//加入队列
        
        while(!q.isEmpty())
        {
            Node cur = q.remove();
            int x =0;
            int y;
            
            for(int i=0; i<num; i++)//查找始结点在数组中的位置
            {
                if(n == node[i])
                {
                    x = i;
                    break;
                }    
            }
            
            for(int j=0; j<num; j++)
            {

                if((cur.x == node[j].x) && (cur.y == node[j].y))//目前结点在数组中的位置
                {
                    y = j;
                    cost[x][y] = t[cur.x][cur.y];
                    break;
                }
            }
            
            for(int i=0; i<4; i++)//下,上,右,左
            {
                int tx = cur.x + dir[i][0];
                int ty = cur.y + dir[i][1];
                
                Node next = new Node();
                
                if(tx >= 0 && tx < r && ty >=0 && ty < c)
                    if(map[tx][ty] != '#' && t[tx][ty] < 0)
                        {
                            next.x = tx;
                            next.y = ty;
                            t[tx][ty] = t[cur.x][cur.y] + 1;
                            q.add(next);
                        }
            }
        }
    }
    
    
    void prim()
    {
//        boolean vist[][] = new boolean[r][c];
        int lowcost[] = new int[num];
        ans = 0;
        
        for(int i=1; i<num; i++)
        {
            lowcost[i] = cost[0][i];
        }
        
        for(int i=1; i<num; i++)
        {
            int minum = Integer.MAX_VALUE;
            int tmp = 0;
            
            for(int j=0; j<num; j++)
            {
                if(lowcost[j] > 0 && minum > lowcost[j])
                {
                    minum = lowcost[j];
                    tmp = j;
                }
            }
            
            if(minum != Integer.MAX_VALUE)
                ans += minum;
            
            lowcost[tmp] = 0;
            
            for(int j=0; j<num; j++)
            {
                if(cost[tmp][j] < lowcost[j])
                {
                    lowcost[j] = cost[tmp][j];
                }
            }
            
        }
    }
    
    void output()
    {
        System.out.println(ans);
    }
    
    public static void main(String args[])
    {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();//迷宫数
        
        while(n-->0)
        {
             c = cin.nextInt();//迷宫列数
             r = cin.nextInt();//行数
            
            map = new char[r][c];
            node = new Node[102];//用于存储结点A,S
            
            cin.nextLine();
            for(int i=0; i<r; i++)
                map[i] = cin.nextLine().toCharArray();
            
             BorgMaze bm = new  BorgMaze();
             num = 0;
            
             for(int i=0; i<r; i++)
                 for(int j=0; j<c; j++)
                 {
                     if(map[i][j] == 'A' || map[i][j] == 'S')
                     {
                         Node now = new Node();
                         now.x = i;
                         now.y = j;
                        
                         node[num] = now;
                         num++;
                        
                     }
                 }
            
             cost = new int[num][num];
             //对每个结点分别求出它到其他结点的距离
             for(int i=0; i<num; i++)
             {
                 bm.bfs(node[i]);
             }
            
             //求最小生成树
             bm.prim();
             bm.output();
        }
        
        cin.close();
    }
}
原创粉丝点击