J - Borg Maze
POJ - 3026
The Borg is an immensely powerful race of enhanced humanoids from the delta quadrant of the galaxy. The Borg collective is the term used to describe the group consciousness of the Borg civilization. Each Borg individual is linked to the collective by a sophisticated subspace network that insures each member is given constant supervision and guidance.
Your task is to help the Borg (yes, really) by developing a program which helps the Borg to estimate the minimal cost of scanning a maze for the assimilation of aliens hiding in the maze, by moving in north, west, east, and south steps. The tricky thing is that the beginning of the search is conducted by a large group of over 100 individuals. 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.). The cost of searching a maze is definied as the total distance covered by all the groups involved in the search together. That is, if the original group walks five steps, then splits into two groups each walking three steps, the total distance is 11=5+3+3.
Input
On the first line of input there is one integer, N <= 50, giving the number of test cases in the input. Each test case starts with a line containg two integers x, y such that 1 <= x,y <= 50. After this, y lines follow, each which x characters. For each character, a space `` '' stands for an open space, a hash mark ``#'' stands for an obstructing wall, the capital letter ``A'' stand for an alien, and the capital letter ``S'' stands for the start of the search. The perimeter of the maze is always closed, i.e., there is no way to get out from the coordinate of the ``S''. At most 100 aliens are present in the maze, and everyone is reachable.
Output
For every test case, output one line containing the minimal cost of a succesful search of the maze leaving no aliens alive.
Sample Input
2
6 5
#####
#A#A##
# # A#
#S ##
#####
7 7
#####
#AAA###
# A#
# S ###
# #
#AAA###
#####
Sample Output
8
11
题意:大体意思是说,给你一个图,S是起点,A是外星人,然后告诉你,需要从S点出发,经过最短的距离找到所有的外星人。
需要注意的是,经过S点和A点是可以分裂的。
思路:今天刚好学习最小生成树的专题,就来写了一下这个题,刚做到这个题的时候,没大读懂什么意思,借助各种翻译工具,算是理解了题目的要求,可以把A 和 S 看成特殊点,在特殊点进行分支,可以联想到建树,而每两个点的距离就是各边的权值,先用BFS 跑一边,求出没两点之间的距离,然后再用最小生成树找一边,得出来的就是最小的成本啦。
PS:这个题难度并不高,但是在做的时候WA了好几次,测试了好多组数据都挺对的,在拜读了大神的博客之后,才知道输入行和列之后不能用getchar() 接收换行,因为后面会有许多空格,所以要用gets()。
话不多说,直接上AC代码:
Kruskal:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#define INF 0x3f3f3f3f
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define fori(x) for(int i=0;i<x;i++)
#define forj(x) for(int j=0;j<x;j++)
#define memset(x,y) memset(x,y,sizeof(x))
#define memcpy(x,y) memcpy(x,y,sizeof(x))
//#include <bits/stdc++.h>
const int maxn=1e6+7;
const int mod=1e9+7;
const double eps=1e-8;
using namespace std;
int n,m,k;
int cnt,num;
int a,b;
int point[66][66];
int visit[66][66];
char maps[66][66];
int dir[4][2]={1,0,-1,0,0,1,0,-1};
struct Point
{
int x,y;
int step;
};
int f[maxn];
struct node
{
int u,v;
int cost;
}e[maxn];
bool cmp(node a,node b)
{
return a.cost<b.cost;
}
int find(int x)//并查集找父节点并压缩路径
{
return f[x]==x ? x : f[x]=find(f[x]);
}
bool ff(Point a)//判断点时候符合条件
{
if(a.x>=0 && a.x<n && a.y>=0 && a.y<m && maps[a.x][a.y]!='#' && !visit[a.x][a.y])
return true;
return false;
}
void bfs(int sx,int sy)
{
memset(visit,0);
Point fr,se;
queue<Point>q;
fr.x=sx;
fr.y=sy;
fr.step=0;
visit[sx][sy]=1;
q.push(fr);
while(!q.empty())
{
fr=q.front();
q.pop();
for(int i=0;i<4;i++)
{
se.x=fr.x+dir[i][0];
se.y=fr.y+dir[i][1];
se.step=fr.step+1;
if(ff(se))
{
visit[se.x][se.y]=1;
q.push(se);
if(maps[se.x][se.y]=='A' || maps[se.x][se.y]=='S' )
{
e[num].u=point[sx][sy];
e[num].v=point[se.x][se.y];
e[num++].cost=se.step;
}
}
}
}
}
int kruskal(int n)
{
int mincost=0;
rep(i,0,cnt)
f[i]=i;
rep(i,0,n)
{
int u=e[i].u;
int v=e[i].v;
int fu=find(u);
int fv=find(v);
if(fu!=fv)
{
f[fu]=fv;
mincost+=e[i].cost;
}
}
return mincost;
}
int main()
{
int t;
char tmp[maxn];
scanf("%d",&t);
while(t--)
{
memset(point,0);
scanf("%d%d",&m,&n);
gets(tmp);
cnt=0;
num=0;
rep(i,0,n)
{
gets(maps[i]);
rep(j,0,m)
{
if(maps[i][j]=='A' || maps[i][j]=='S')
point[i][j]=cnt++;//给每个点标号
}
}
rep(i,0,n)
rep(j,0,m)
{
if(maps[i][j]=='A' || maps[i][j]=='S')
bfs(i,j);
}
sort(e,e+num,cmp);
printf("%d\n",kruskal(num));
}
return 0;
}
Prime:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#define INF 0x3f3f3f3f
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define fori(x) for(int i=0;i<x;i++)
#define forj(x) for(int j=0;j<x;j++)
#define memset(x,y) memset(x,y,sizeof(x))
#define memcpy(x,y) memcpy(x,y,sizeof(x))
//#include <bits/stdc++.h>
const int maxn=1e6+7;
const int mod=1e9+7;
const double eps=1e-8;
using namespace std;
int n,m,k;
int cnt,num;
int a,b;
int point[666][666];
int visit[666][666];
int vis[666];
int edge[666][666];//各边权值
int dis[666];
char maps[666][666];
int dir[4][2]={1,0,-1,0,0,1,0,-1};
struct Point
{
int x,y;
int step;
};
bool ff(Point a)
{
if(a.x>=0 && a.x<n && a.y>=0 && a.y<m && maps[a.x][a.y]!='#' && !visit[a.x][a.y])
return true;
return false;
}
void bfs(int sx,int sy)
{
memset(visit,0);
Point fr,se;
queue<Point>q;
fr.x=sx;
fr.y=sy;
fr.step=0;
visit[sx][sy]=1;
q.push(fr);
while(!q.empty())
{
fr=q.front();
q.pop();
for(int i=0;i<4;i++)
{
se.x=fr.x+dir[i][0];
se.y=fr.y+dir[i][1];
se.step=fr.step+1;
if(ff(se))
{
visit[se.x][se.y]=1;
q.push(se);
if(maps[se.x][se.y]=='A' || maps[se.x][se.y]=='S' )
{
edge[point[sx][sy]][point[se.x][se.y]]=se.step;
}
}
}
}
}
void Prime()
{
int sum = 0;
rep(i,1,cnt+1) dis[i] = INF;
dis[1] = 0;
memset(vis, 0);
rep(i,1,cnt+1)
{
int u, minn = INF;
rep(j,1,cnt+1)
if(!vis[j] && dis[j] <= minn)
minn = dis[u=j];
vis[u] = 1;
sum += dis[u];
rep(j,1,cnt+1)
if(!vis[j])
dis[j] = min(dis[j], edge[u][j]);
}
printf("%d\n",sum);
}
int main()
{
int t;
char tmp[maxn];
scanf("%d",&t);
while(t--)
{
memset(edge,maxn);
memset(point,0);
scanf("%d%d",&m,&n);
gets(tmp);
cnt=0;
rep(i,0,n)
{
gets(maps[i]);
rep(j,0,m)
{
if(maps[i][j]=='A' || maps[i][j]=='S')
point[i][j]=++cnt;
}
}
rep(i,0,n)
rep(j,0,m)
{
if(point[i][j])
bfs(i,j);
}
Prime();
}
return 0;
}
本文介绍了一道关于迷宫搜索的算法题,重点在于使用最小生成树算法找到搜索迷宫的最小成本。通过BFS算法计算特殊点间的距离,并采用Kruskal或Prim算法构造最小生成树。
&spm=1001.2101.3001.5002&articleId=81413969&d=1&t=3&u=d374edc3bf724f2590a56cfb50879050)
723

被折叠的 条评论
为什么被折叠?



