G - Borg Maze (Prim&BFS)

G - Borg Maze (Prim&BFS)

题意:给一个图,起点S,求遍历到所有‘A’的最小距离之和.每次走到一个‘A’相当于这个’A’是新的起点’S‘,很显然会想到树,新的子结点作为根结点继续往下搜索.所以此题为最小生成树问题。具体看代码。

AC代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue> 
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
int r,c;
const int N=205,inf=0x3f3f3f3f;
char mp[N][N];
int pos[N][N],cnt=0,vis[N][N],dis[N][N];//pos[i][j]记录S或A的位置,vis[i][j]即作为标记也作为距离使用。 
struct zb{
	int x,y;
}now; 
int dw[4][2]={0,1,0,-1,1,0,-1,0};
void bfs(int sx,int sy){
	queue<zb>q;
	memset(vis,-1,sizeof vis);//初始化-1保证起点到自己的距离为0. 
	q.push({sx,sy}),vis[sx][sy]=0;
	while(q.size()){
		now=q.front();q.pop();
		if(pos[now.x][now.y]) dis[pos[sx][sy]][pos[now.x][now.y]]=vis[now.x][now.y];
		for(int i=0;i<4;i++){
			int nx=now.x+dw[i][0],ny=now.y+dw[i][1];
			if(vis[nx][ny]==-1&&mp[nx][ny]!='#'&&nx>=1&&nx<=r&&ny>=1&&ny<=c)
			{
				vis[nx][ny]=vis[now.x][now.y]+1;
				q.push({nx,ny});
			}
		}
	}
}
int  prim(){
	int jg[N]={},w[N]={},ans=0;
	jg[1]=1;//任取一个点开始贪心操作. 
	for(int i=2;i<=cnt;i++) w[i]=dis[1][i];//初始化. 
	for(int i=2;i<=cnt;i++)
	{
		int mn=inf,id=0;
		for(int j=1;j<=cnt;j++){ //找到距离集合最近的邻居. 
			if(!jg[j]&&w[j]<mn){
				mn=w[j];
				id=j;
			}
		}
		if(mn==inf) break;
		ans+=mn;
		jg[id]=1;
		for(int j=1;j<=cnt;j++)
			if(!jg[j]&&dis[id][j]<w[j]) //每次集合中加入一个点就用这个点对其他点松弛. 
				w[j]=dis[id][j];
	}
	return ans;
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		cnt=0,memset(dis,0,sizeof dis),memset(pos,0,sizeof pos);
		scanf("%d%d",&c,&r);
		char ch;
		while((ch=getchar())!='\n') ;//r,c后有空格去除空格. 
		for(int i=1;i<=r;i++){
			gets(mp[i]+1);//为了读取空格. 
			for(int j=1;j<=c;j++){
				 if(mp[i][j]=='S'||mp[i][j]=='A')
				 		pos[i][j]=++cnt;
				 	}
			}
		for(int i=1;i<=r;i++)
			for(int j=1;j<=r;j++)
				if(pos[i][j]) bfs(i,j);
		printf("%d\n",prim());
	}
	return 0;
}
原创文章 151 获赞 134 访问量 6888

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/105655091