当前位置: 代码迷 >> 综合 >> UVa 10307 - Killing Aliens in Borg Maze(图论,最短路,最小生成树)
  详细解决方案

UVa 10307 - Killing Aliens in Borg Maze(图论,最短路,最小生成树)

热度:33   发布时间:2024-01-04 12:00:43.0

题目:在一个迷宫中,以S为起点,遇到A,S时可以分叉,问走到所有的A的路径和最小代价。(一开始读错题意,以为在任意地方都可以分裂,给自己埋了一个大坑,然后发现全世界都过了。。。)

ps:Whenever an alien is assimilated, or at the beginning of the search, the group may split in two or more groups (but their consciousness is still collective.(百度翻译:每当一个外星人被同化,或者在搜索开始时,这个群体可能分裂成两个或更多个群体但他们的意识仍然是集体的)据说这句话表明了用最小生成树(果然只猜题意不看题目是菜)


分析:图论,最短路,最小生成树。利用bfs求出所有的A和A以及A和S间的最短路,再在这个最短路生成的途中计算最小生成树即可。

具体操作过程:

1.先给'S','A'的位置分配编号,表示第几个分裂点

2.初始化分裂点之间的边,小标用编号表示,自己到自己,否则无穷大

3.bfs,如果下一个点是‘#’则不能走,不入队,走过了也不入队(保证最优),入队时到bfs起点的步长+1

4.最小生成树(因为是稀疏图用kruskal


代码:

#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
typedef long long ll;
const int N=500+20;
char s[N][N];
int num[N][N],e[N][N],vis[N][N],tot,n,m;
int dis[N],vis2[N];
int go[4][2]= {1,0,-1,0,0,1,0,-1};
struct node
{
    int x,y,step;
};
void bfs(int x,int y)
{
    mem(vis,0);
    node now,to;
    now.x=x,now.y=y,now.step=0;
    vis[x][y]=1;
    queue<node>q;
    q.push(now);
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        if(num[now.x][now.y])
            e[num[x][y]][num[now.x][now.y]]=now.step;
        for(int i=0; i<4; i++)
        {
            int xx=now.x+go[i][0];
            int yy=now.y+go[i][1];
            if(xx>=0&&xx<n&&yy>=0&&yy<m&&!vis[xx][yy]&&s[xx][yy]!='#')
            {
                vis[xx][yy]=1;
                to.x=xx,to.y=yy,to.step=now.step+1;
                q.push(to);
            }
        }
    }
    return;
}
int prim()
{
    for(int i=1; i<=tot; i++)
    {
        dis[i]=inf;
        vis2[i]=0;
    }
    vis2[1]=1;
    dis[1]=0;
    int ans=0;
    for(int i=0; i<=tot; i++)
    {
        int minn=inf,k=1;
        for(int j=1; j<=tot; j++)
            if(!vis2[j]&&dis[j]<minn)
            {
                minn=dis[j];
                k=j;
            }
        vis2[k]=1;
        ans+=dis[k];
        for(int j=1; j<=tot; j++)
            if(!vis2[j]&&e[k][j]<dis[j])
                dis[j]=e[k][j];
    }
    return ans;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        tot=1;
        mem(num,0);
        scanf("%d%d\n",&m,&n);
        for(int i=0; i<n; i++)
        {
            gets(s[i]);
            for(int j=0; j<m; j++)
                if(s[i][j]=='S'||s[i][j]=='A')
                    num[i][j]=tot++;
        }
        for(int i=1; i<=tot; i++)
            for(int j=1; j<=tot; j++)
                e[i][j]=i==j?0:inf;
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                if(num[i][j])
                    bfs(i,j);
        printf("%d\n",prim());
    }
    return 0;
}

  相关解决方案