每日一题(7):poj3026,BorgMaze

1.      题意比较难理解的地方就是会分成几组,其实不用管。因为最小生成树,无论怎么分,无论谁来走,只要最后计算的是最小生成树的最后权值即可。

2.      另一点就是思路。知道肯定要用最小生成树。但是因为每两点间的距离并没有给出来。所以需要先获得距离矩阵。需要用bfs。但是不是传统的bfs,因为这里要求得是全部点间的最短距离。需要使用循环来利用bfs,每次求一个点到其他点间的距离。另外,即使bfs算法本身,也有所不同。这里用了迭代而不是递归。因为要反复用到初始起点,如果用递归的话稍微有点麻烦。然后就是根据起始点到每一个可达点的最短距离(bfs),找出节点间的距离矩阵。而后prim。

3.      当然,由于一定有通路,节省了不少

4.      bfs里面和prim里面的dist不要搞混。

5.      参考链接http://blog.csdn.net/lyy289065406/article/details/6645991

6.      340K 16MS

7.      还有一点值得一提,就是这里用了队列。使用队列还实现bfs。因为需要一个遍历所有点的循环。感觉这是一个很巧妙的方法。我们只需要把新点加入,就可以使用bfs了。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
using namespace std;

const int inf = 2600;//无穷
const int maxs = 51;//原始map最值
const int maxs2 = 102;//最小生成树里面的点的最值
char map[maxs][maxs];//原始map
int X[4]={0,1,0,-1};//上下左右
int Y[4]={-1,0,1,0};
int num; //生成树的点数
int n,y,x; //test cases
int dist[maxs2][maxs2];//最短路距离矩阵
//int index ;
//int w,h;
int node[maxs][maxs];//从map到dist的转换
void bfs(int sx, int sy)

{
    //直接用递归不合适,因为每次都需要最开始的起始点坐标。
    bool flag[maxs][maxs];//标记是否访问过
    int queryx[2501];//访问点的队列
    int queryy[2501];
    int head=0,tail = 0;//头尾指针
    queryx[tail] = sx;
    queryy[tail++] = sy;//装入起始点
    flag[sx][sy] = false;
    int mapDist[maxs][maxs];//表示每个可达点到起始点的距离

    for(int i = 0; i<maxs; i++)//初始化
    {
        for(int j = 0; j < maxs; j++)
        {
            flag[i][j] = true;
            mapDist[i][j] = 0;
        }
    }

    while(head<tail)
    {
        int sx2 = queryx[head];
        int sy2 = queryy[head++];
        for(int i = 0; i<4; i++)
        {
            int nextx = sx2 +X[i];
            int nexty = sy2+Y[i];
            if(flag[nextx][nexty]&&nextx>=0&&nextx<x&&nexty>=0&&nexty<y)
            {
                if(map[nextx][nexty]!='#')
            {
                //bfs的每步操作
                queryx[tail] = nextx;
                queryy[tail++] = nexty;
                flag[nextx][nexty] = false;
               mapDist[nextx][nexty] =
                mapDist[sx2][sy2]+1;

            }
                if(map[nextx][nexty]=='A')
            {
                //构建节点距离矩阵
               dist[node[sx][sy]][node[nextx][nexty]] = mapDist[nextx][nexty];
            }

            }

        }
    }
}
int prim()
{
    int s = 1;

    int minw ;
    bool flag[maxs2];
    int minDist[maxs2];
    int flagPoint;
    int result = 0;
    int m = 1;

    for(int i = 1; i<maxs2; i++)
    {
        flag[i] = true;
        minDist[i] = inf;
    }

    while(m!=num)
    {
        minw = inf;
        for(int i = 2; i<=num;i++)
        {
           
            if(flag[i]&&minDist[i]>dist[s][i])
            {
                minDist[i] = dist[s][i];
               
            }
            if(flag[i] && minw>minDist[i])
            {
                minw = minDist[i];
                flagPoint = i;
            }
        }
        s = flagPoint;
        flag[s] = false;
        result +=minw;
        m++;
    }
    return result;

}
int main()
{
    //freopen("input.txt","r",stdin);//文件读入
    cin>>n;
    while(n--)
    {
        num = 0;
        cin>>x>>y;
        // index = 0;
        char temp[51];

        gets(temp);

        for(int i = 0; i<y; i++)
        {
            gets(map[i]);
            for(int j = 0; j<x; j++)
            {
                node[i][j] = 0;
                if(map[i][j]=='S')
                {
                    map[i][j] = 'A';
                }
                if(map[i][j]=='A')
                {
                    node[i][j] = ++num;
                }

            }
            dist[i+1][i+1] = 0;
        }
        for(int i = 0; i<y; i++)
        {
            for(int j = 0; j < x; j++)
            {
                if(node[i][j]!=0)
                {
                    bfs(i,j);
                }
            }
        }

        cout<<prim()<<endl;

    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值