您的位置:首页 > 其它

hrbust 1525 水神【纪念搜索题解100篇】【Bfs】

2016-06-08 18:33 609 查看
水神
Time Limit: 1000 MS

Memory Limit: 16384 K

 

Total Submit: 19(5 users)

Total Accepted: 7(5 users)

Rating: 

Special Judge: No

 
Description

有一片被大海包围的群岛,岛上居住着一个古老的部族。很多年前部落里有一位巫师接受了水神的召唤跳入海中,从此,那一片海域就被打上了水神的烙印,被这片海域所包围的陆地也被赋予了神圣的意义(包围关系满足传递性,即海域A包围了岛B,岛B包围了海域C,而海域C中包含了岛D,则我们说海域A也包含了岛D)。

 

从那以后,部落里的巫师死后都必须葬在这片神圣海域所包围的岛上,而且每一个岛都只能埋葬一位巫师(否则就会被视为对水神的不敬,从而给部族带来灾难)。现在给你群岛的地图和最初那位巫师跳海的地方,请你计算一下最多可以埋葬多少巫师。 

 

地图是一个n*m的字符矩阵,’#’代表陆地,’.’代表海洋。连通的一片陆地为一个岛,连通的一片海洋为一个海域。其中,陆地从上、下、左、右4个方向连通,海洋从上、下、左、右、左上、左下、右上、右下8个方向连通。

如下图。

 图中有4个岛,2片海域。如果在A处落水,则落水的海域包围了除右上、左下两个顶角外的3个岛屿;如果在B处落水,则只包含了中间的2个岛。

 

 

Input

有多组测试数据,不超过10组。

对于每组测试数据,输入的第一行为n, m, x, y, n和m表示地图的大小(1<=n,m<=500),x和y(0 <= x < n, 0 <= y < m)是巫师跳海的地方,数据保证巫师跳海的地方是一个水域。

接下来为一个n*m的字符矩阵,共n行,每行m个字符。

Output

对于每组测试数据,输出一行,包含一个整数,为最多可以埋葬的巫师数量。

Sample Input

7 9 0 0

........#

.#######.

.#.....#.

.#.#.#.#.

.#.....#.

.#######.

#........

7 9 2 6

........#

.#######.

.#.....#.

.#.#.#.#.

.#.....#.

.#######.

#........

Sample Output

3

2

Author

黄李龙@HRBUST

这里纠正一个题目中说明不对的地方,那是5个,不是4个岛。

思路:

1、首先我们统计一下一共有多少岛屿,这里暴力求就可以。

2、根据巫师跳海的地方,我们再Bfs一下,求一下这个围成的海域所组成的界限,对于海域能够扩散所围的地方,我们在vis【】【】中标记为1,如果不能扩散到的地方,标记为0.

3、因为直接求海域内部的岛屿数比较费劲一些,所以我们求海域外的岛屿数,然后用总岛屿数减去海域外岛屿数,即为所求,这里我们找到一个海域外的岛我们就将这个岛变成“.”,以防止多次计算岛屿,或者是计算少岛屿的情况。

AC代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct zuobiao
{
int x,y;
}now,nex;
int n,m,sx,sy,output;
char a[505][505];
int vis[505][505];
int vis2[505][505];
int vis3[505][505];
int fx[8]={0,0,1,-1,1,-1,1,-1};
int fy[8]={1,-1,0,0,1,-1,-1,1};
void Bfs0(int x,int y)//统计一共有多少岛屿
{
queue<zuobiao >s;
now.x=x;
now.y=y;
vis[now.x][now.y]=1;
s.push(now);
while(!s.empty())
{
now=s.front();
s.pop();
for(int i=0;i<4;i++)
{
nex.x=now.x+fx[i];
nex.y=now.y+fy[i];
if(nex.x>=1&&nex.x<=n&&nex.y>=1&&nex.y<=m&&vis[nex.x][nex.y]==0&&a[nex.x][nex.y]=='#')
{
vis[nex.x][nex.y]=1;
s.push(nex);
}
}
}
}
void Bfs(int x,int y)//Bfs能扩散的海域
{
memset(vis,0,sizeof(vis));
queue<zuobiao >s;
now.x=x;
now.y=y;
vis[x][y]=1;
s.push(now);
while(!s.empty())
{
now=s.front();
s.pop();
for(int i=0;i<8;i++)
{
nex.x=now.x+fx[i];
nex.y=now.y+fy[i];
if(nex.x>=1&&nex.x<=n&&nex.y>=1&&nex.y<=m&&vis[nex.x][nex.y]==0&&a[nex.x][nex.y]=='.')
{
vis[nex.x][nex.y]=1;
s.push(nex);
}
}
}
}
void Bfs3(int x,int y)//将海域外的岛屿整个移除
{
memset(vis3,0,sizeof(vis3));
queue<zuobiao >s;
now.x=x;
now.y=y;
vis3[now.x][now.y]=1;
s.push(now);
while(!s.empty())
{
now=s.front();
s.pop();
for(int i=0;i<4;i++)
{
nex.x=now.x+fx[i];
nex.y=now.y+fy[i];
if(nex.x>=1&&nex.x<=n&&nex.y>=1&&nex.y<=m&&vis3[nex.x][nex.y]==0&&a[nex.x][nex.y]=='#')
{
vis3[nex.x][nex.y]=1;
s.push(nex);
a[nex.x][nex.y]='.';
}
}
}
}
void Bfs2(int x,int y)//找海域外的岛屿
{
memset(vis2,0,sizeof(vis2));
now.x=x;
now.y=y;
queue<zuobiao >s;
s.push(now);
vis2[x][y]=1;
while(!s.empty())
{
now=s.front();
s.pop();
for(int i=0;i<4;i++)
{
nex.x=now.x+fx[i];
nex.y=now.y+fy[i];
if(nex.x>=0&&nex.x<=n+1&&nex.y>=0&&nex.y<=m+1&&vis2[nex.x][nex.y]==0&&vis[nex.x][nex.y]==0)
{
vis2[nex.x][nex.y]=1;
if(a[nex.x][nex.y]=='#')
{
output++;//每一次在海域外找到一个岛屿,都计数一次。
Bfs3(nex.x,nex.y);
}
else
{
s.push(nex);
}
}
}
}
}
int main()
{
while(~scanf("%d%d%d%d",&n,&m,&sx,&sy))
{
memset(a,'.',sizeof(a));
memset(vis2,0,sizeof(vis2));
memset(vis3,0,sizeof(vis3));
memset(vis,0,sizeof(vis));
output=0;
sx++;sy++;
for(int i=1;i<=n;i++)
{
scanf("%s",a[i]+1);
}
memset(vis,0,sizeof(vis));
int cont=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(vis[i][j]==0&&a[i][j]=='#')
{
cont++;
Bfs0(i,j);
}
}
}
Bfs(sx,sy);
Bfs2(0,0);
printf("%d\n",cont-output);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息