poj 3026 Borg Maze (bfs+最小生成树)

题目链接: http://poj.org/problem?id=3026

题意:一对警察(S)抓捕外星人(A),‘#’代表墙,‘_’(空格)代表可以通过的路,从S处出发,问最少走多长的路可以把外星人全部KO了!注意:当他们在S处或是当抓捕到某个外星人以后,可以分开成几个队伍向周围继续抓捕,总的路程等于每支队伍的总和!

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#define N 130
#define INF 0x3f3f3f3f
using namespace std;
int n, k;
bool vis[N*N];
int dis[N][N], lostcow[N*N];
int map[N][N], cost[N][N];
char str[N][N];
int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
void bfs(int x, int y)
{
    int tx, ty, i, ttx, tty;
    queue<pair<int, int> >Q;
    memset(dis, 0, sizeof(dis));
    Q.push(make_pair(x, y));
    dis[x][y] = 0;
    while(!Q.empty())
    {
        tx = Q.front().first, ty = Q.front().second;
        Q.pop();
        if(map[tx][ty])
            cost[map[x][y]][map[tx][ty]] = dis[tx][ty];/*   cost用于存字母和字母间的权值    */
        for(i = 0; i < 4; i++)
        {
            ttx = tx + dx[i], tty = ty + dy[i];
            if(ttx >= 0 && ttx < k && tty >= 0 && tty < n)
            {
                if(str[ttx][tty] == '#' || dis[ttx][tty])
                    continue;
                dis[ttx][tty] = dis[tx][ty] + 1;
                Q.push(make_pair(ttx, tty));
            }
        }
    }
}
int prim(int nn)
{
    int sum = 0, i, j, m;
    memset(vis, 0, sizeof(vis));
    for(i = 1; i <= nn; i++)
        lostcow[i] = cost[1][i];
    vis[1] = 1;
    for(i = 1; i < nn; i++)
    {
        m = 1;
        int min = INF;
        for(j = 1; j <= nn; j++)
            if(!vis[j] && lostcow[j] < min)
            {
                min = lostcow[j];
                m = j;
            }
        vis[m] = 1;
        if(min != INF)
            sum += min;
        for(j = 1; j <= nn; j++)
            if(!vis[j] && lostcow[j] > cost[m][j])
                lostcow[j] = cost[m][j];
    }
    return sum;
}
int main()
{
    int t, i, j;
    scanf("%d", &t);
    while(t--)
    {
        int num = 1;
        memset(map, 0, sizeof(map));
        memset(cost, 0, sizeof(cost));
        scanf("%d%d", &n, &k);
        gets(str[0]);/*     用getchar()不行    */
        for(i = 1; i <= k; i++)
        {
            gets(str[i]);
            for(j = 1; j <= n; j++)
                if(str[i][j] == 'A' || str[i][j] == 'S')/*      字母和字母之间建最小生成树     */
                    map[i][j] = num++;
        }
        for(i = 1; i <= k; i++)
            for(j = 1; j <= n; j++)
                if(map[i][j])
                    bfs(i, j);/*    求每个字母之间的权值      */
        printf("%d\n", prim(num-1));
    }
    return 0;
}

 

posted @ 2015-09-24 19:23  byonlym  阅读(187)  评论(0编辑  收藏  举报