【POJ - 3026】Borg Maze(bfs预处理 + 最小生成树,建图)

题干:

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

题目大意:

这个题意是真难懂啊、、、

在一个迷宫中有很多外星人A,某个人在S点开始去抓捕,抓捕到外星人后这个人可以分身为任意个(也可以不分身),求把所有外星人抓完所用的最小距离,距离包括分身走的距离(即所有的距离都算上,比如:两个分身同时走三步,那么走的距离就是6,而不是3),在迷宫之中只能向东南西北四个方向移动。

换种说法:

给你一个地图,地图中A代表外星人,S代表出发点,从S点出发,在起点S 或是 每遇到一个A点 便可不分裂或是分裂成多个。求把所有A都吃完需要多少步。注意不要以为当前点随时都能分裂,而是只有在S或是遇到A才能分裂。

解题报告:

  注意这题样例 n m 和字符串之间可能有一行空行(而不一定是一个空格)真tm格式、、所以getchar会WA的。。

因为不难发现,既然这个题意的话,那么起点在哪并没有怎么所谓了,因为S的所有特点和A的所有特点是完全相同的,所以可以把S点也看成是一个A点,那么题意转化成:从一个A点出发,在所有A点相连的路径中选择一些路径,使得走过的路最小。

那么解法很显然了,假设有tot个S和A,那么用bfs构造出这tot个点之间的距离,然后求个MST就好,因为稠密图而且是完全图所以首选prim。

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 200 + 5;
const int INF = 0x3f3f3f3f;
int n,m;
char s[MAX][MAX];
int bk[MAX][MAX],cost[MAX][MAX],tot;
bool vis[MAX][MAX];
int nx[4] = {0,1,0,-1};
int ny[4] = {1,0,-1,0};
struct Node {
	int x,y,t;
	Node(int x=0,int y=0,int t=0):x(x),y(y),t(t){}
};
void bfs(int stx,int sty) {
	int id1 = bk[stx][sty];
	queue<Node> q;
	q.push(Node(stx,sty,0));
	memset(vis,0,sizeof vis);
	vis[stx][sty]=1;
	while(!q.empty()) {
		Node cur = q.front();q.pop();
		int id2 = bk[cur.x][cur.y];
		if(bk[cur.x][cur.y]) cost[id1][id2] = cur.t;
		for(int k = 0; k<4; k++) {
			int tx = cur.x+nx[k];
			int ty = cur.y+ny[k];
			if(tx<0||tx>n||ty<1||ty>m) continue;
			if(vis[tx][ty] || s[tx][ty] == '#') continue;
			vis[tx][ty] = 1;
			q.push(Node(tx,ty,cur.t+1));
		}
	}	
}
int VIS[MAX*MAX],dis[MAX*MAX];
int prim() {
	int res = 0;
	for(int i = 1; i<=tot; i++) dis[i] = INF,VIS[i] = 0;
	dis[1] = 0;
	while(1) {
		int minv,minw=INF;
		for(int i = 1; i<=tot; i++) {
			if(VIS[i] == 0 && dis[i] < minw) minw = dis[i],minv = i;
		}
		if(minw == INF) break;
		VIS[minv] = 1;
		for(int i = 1; i<=tot; i++) {
			if(VIS[i] == 0 && dis[i] > cost[minv][i]) dis[i] = cost[minv][i];
		}
		res += dis[minv];
	}
	return res;		
}
int main()
{
	int t;
	cin>>t;
	while(t--) {
		tot=0;
		memset(bk,0,sizeof bk);
		memset(cost,0,sizeof cost);
		scanf("%d%d",&m,&n);
		string qq;getline(cin,qq);
		for(int i = 1; i<=n; i++) {
			cin.getline(s[i]+1,1005);
			for(int j = 1; j<=m; j++) {
				if(s[i][j] == 'S' || s[i][j] == 'A') bk[i][j] = ++tot;
			}
		}
		for(int i = 1; i<=n; i++) {
			for(int j = 1; j<=m; j++) {
				if(bk[i][j]) bfs(i,j);
			}
		}
		printf("%d\n",prim());
	} 
	
	return 0 ;
}

刚开始WA在数组就开了50*50这么大,导致cost数组也开了[50][50],但是其实应该[2501][2501],但是其实这题说了最多100个外星人,所以可以开[105][105]就够了。

全部评论

相关推荐

吐泡泡的咸鱼:我也工作了几年了,也陆陆续续面试过不少人,就简历来说,第一眼学历不太够,你只能靠你的实习或者论文或者项目经历,然后你没有论文,没有含金量高的比赛和奖项,只能看实习和项目,实习来说,你写的实习经历完全不清楚你想找什么工作?行研?数据分析?且写的太少了,再看项目,这些项目先不说上过大学读过研究生的都知道很水,然后对你想找的岗位有什么帮助呢?项目和实习也完全不匹配啊,你好像在努力将你所有的经历都放在简历里想表现你的优秀,但是对于你想找的岗位来说,有什么用呢?最后只能获得岗位不匹配的评价。所以你需要明白你想要找的岗位要求是什么,是做什么的,比如产品经理,然后再看你的经历里有什么匹配的上这个岗位,或者对这个岗位以及这个岗位所在的公司有价值,再写到你的简历上
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务