POJ3026,Borg Maze(BFS+最小生成树)

第一次接触BFS居然是和最小生成树结合在一起的。
一开始是用DFS求各个A及S之间的最短路径,严重超时。。。网上求助大佬后才知道要用BFS,结果超快!
代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
char s[55][55];
int map[105][105],dis[105],pos[105][2];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}},h,l;
bool vis[105],visited[55][55];	//visited[]记录每个块是否已经被访问过
struct block
{
	int id,x,y;
	int mov;
	block()
	{
		mov=0;
	}
}blo[55][55];

int Prim(int n)
{
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		vis[i]=0;
		dis[i]=map[1][i];
	}
	vis[1]=1;
	for(int i=1;i<=n;i++)
	{
		int temp=1005,k;
		for(int j=1;j<=n;j++)
			if(!vis[j]&&temp>dis[j])
				temp=dis[k=j];
		if(temp==1005)
			break;
		ans+=dis[k];
		vis[k]=1;
		for(int j=1;j<=n;j++)
			if(!vis[j]&&dis[j]>map[k][j])
				dis[j]=map[k][j];
	}
	return ans;
}

void BFS(int x,int y,int id)
{
	queue<block> q;		//BFS要借助队列进行操作,不同与DFS一般用递归
	block u;
	u.id=id; u.x=x; u.y=y;
	q.push(u);
	memset(visited,0,sizeof(visited));
	visited[x][y]=1; 	//起点已经被访问过了,故设其为1
	while(!q.empty())
	{
		block fro=q.front(); q.pop();
		if(fro.id>=1)		//>=1说明这里是A或是S,与我下面输入后的处理有关
		{
			map[u.id][fro.id]=fro.mov;	//BFS是由一个点源以辐射状传播开来,因此每个块只会被访问一次(visited[]的作用),且被访问时必然为最小路径,故可以不用min函数
			map[fro.id][u.id]=map[u.id][fro.id];
		}
		for(int i=0;i<=3;i++)
		{
			int x0=fro.x+dir[i][0],y0=fro.y+dir[i][1];
			if(x0>=1&&x0<=h&&y0>=0&&y0<l)
			{
				if(blo[x0][y0].id>=0&&!visited[x0][y0])
				{
					block a;
					a.id=blo[x0][y0].id;
					a.x=x0; a.y=y0;
					a.mov=fro.mov+1;
					q.push(a);
					visited[x0][y0]=1;	//莫忘了这步
				}
			}
		}
	}
	return ;
 } 

int main()
{
	int n,cnt;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d%d",&l,&h);
		cnt=1;
		char s0[105];
		gets(s0);	//这道题有个坑,输入l,h后后面会有一堆空格,用getchar()会WA,因此得用gets
		for(int i=1;i<=h;i++)
			gets(s[i]);
		for(int i=1;i<=h;i++)
			for(int j=0;j<l;j++)
			{
				if(s[i][j]=='A')
				{
					cnt++;
					blo[i][j].id=cnt;
					pos[cnt][0]=i;
					pos[cnt][1]=j;
				}
				else if(s[i][j]=='S')
				{
					blo[i][j].id=1;
					pos[1][0]=i;
					pos[1][1]=j;
				}
				else if(s[i][j]==' ')
					blo[i][j].id=0;
				else blo[i][j].id=-1;
				blo[i][j].x=i; blo[i][j].y=j;
			}
		for(int i=1;i<=cnt;i++)
			for(int j=1;j<=cnt;j++)
				map[i][j]=1005;
		for(int i=1;i<cnt;i++)
			BFS(pos[i][0],pos[i][1],i);
		map[cnt][cnt]=0;
		printf("%d\n",Prim(cnt));
	}
	return 0;
}

小结:
1.BFS是由一个点源,以辐射状传播出去的;
2.BFS要借助队列进行实现;
3.BFS要借助一个visited[]数组,保证每个方块只会被访问一次;
4.BFS访问到某个方块时,该方块到点源的路径必然是最小路径(因为2)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值