hrbust 1525 水神【纪念搜索题解100篇】【Bfs】
2016-06-08 18:33
609 查看
水神 | ||||||
| ||||||
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 |
思路:
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);
}
}
相关文章推荐
- Linux之进程调度
- SQL server 2008 R2 MSSQLSERVER 无法启动 error code 17058.
- Android Gradle 技巧之二: 最爱命令行
- smail语句学习
- Windows API 编程----EnumWindows()函数的用法
- Linux 使用unzip命令解压其中的单个文件到指定文件夹
- 日常开发bug修复——火狐浏览器提交表单时表单执行两次
- Eclipse 实用快捷键收集
- QT 静态编译后中文可能会出现乱码
- Bootstap
- 配置当前用户使用豆瓣pip源
- iOS已上线应用的推送证书过期的处理
- Unity3D LuaBundleLoader(基于cslua)
- B树、B-树、B+树、B*树
- Android Gradle 技巧之二: 最爱命令行
- JavaScript中instanceof运算符的使用示例
- 基于android的Http网络请求
- hive内部表与外部表区别
- 160608、mysql距离函数st_distance
- [caffe]extract feature