poj3026 - Borg Maze

133 篇文章 0 订阅

                                   想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410
                                     转载请注明出处:
http://blog.csdn.net/wangjian8006

题目大意:给出一个二维字符串,里面有#代表不能走,' '空格代表可以走,然后还有'A'和'S'代表人,问从S到达所有'A'的最小通路,就是最小生成树
解题思路:因为说了上面的A不会超过100个,所以开个102的数组够了,用BFS找出任意两点相距的最小距离保存在图中之后prim就可以了,前面看错题目以为x,y<=50就以为开个50的数组可以了,结果不断RE,后来开大才A了

 

/*
Memory 284K
Time   63MS
*/
#include <iostream>
#include <queue>
using namespace std;
#define MAXV 102
#define inf 1<<29

typedef struct{
	int x,y;
}Point;

Point point[MAXV];
char s[MAXV][MAXV];
int m,n,psum,map[MAXV][MAXV];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};

void findpoint(){
	int i,j;
	psum=1;
	for(i=0;i<m;i++)
		for(j=0;j<n;j++)
			if(s[i][j]=='A'){
				point[psum].x=i;
				point[psum++].y=j;
			}else if(s[i][j]=='S'){
				point[0].x=i;
				point[0].y=j;
			}
}

void bfs(int start){
	int discover[MAXV][MAXV],dis[MAXV][MAXV];
	queue <int> q;
	int i,a,b,tx,ty;

	for(i=0;i<m;i++)
		for(int j=0;j<n;j++){
			dis[i][j]=0;
			discover[i][j]=0;
		}

	a=point[start].x;
	b=point[start].y;
	q.push(a);
	q.push(b);
	discover[a][b]=true;

	while(!q.empty()){
		a=q.front();q.pop();
		b=q.front();q.pop();
		for(i=0;i<4;i++){
			tx=a+dx[i];
			ty=b+dy[i];
			if(!discover[tx][ty] && tx>=0 && tx<n && ty>=0 && ty<m && s[tx][ty]!='#'){
				dis[tx][ty]=dis[a][b]+1;
				discover[tx][ty]=true;
				q.push(tx);
				q.push(ty);
			}
		}
	}
	for(i=0;i<psum;i++){
		int t=dis[point[i].x][point[i].y];
		if(t) map[start][i]=t;
	}
}

void prim(){
	int i,j,v;
	int d[MAXV],vis[MAXV];
	for(i=0;i<psum;i++){
		d[i]=map[0][i];
		vis[i]=0;
	}
	
	for(i=0;i<psum;i++){
		int min=inf;
		for(j=0;j<psum;j++)
			if(!vis[j] && d[j]<min){
				min=d[j];
				v=j;
			}
			
			vis[v]=1;
			
			for(j=0;j<psum;j++){
				if(!vis[j] && map[v][j]<d[j])
					d[j]=map[v][j];
			}
	}
	int ans=0;
	for(i=0;i<psum;i++) ans+=d[i];
	printf("%d\n",ans);
}

int main(){
	int t,i;
	scanf("%d\n",&t);
	while(t--){
		gets(s[0]);
		sscanf(s[0],"%d%d",&n,&m);

		for(i=0;i<m;i++) gets(s[i]);
		findpoint();					//找到点的坐标
		for(i=0;i<psum;i++) bfs(i);				//计算距离
		prim();						//最小生成树
	}
	return 0;
}


 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值