第一次接触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)。