搜索分为DFS和BFS(深度优先搜索和广度优先搜索),dfs的基础题型可见排列组合问题,这篇文章主要记录一下遇到的几种连通块问题。
如果把深度优先搜索和广度优先搜索比作两个人的话,这两个人像性格迥异的双胞胎,哥哥DFS的性格很“执拗”,不撞南墙不回头,弟弟BFS的性格很沉稳,一步一步来hh
一矩形阵列由数字 0 0 0 到 9 9 9 组成,数字 1 1 1 到 9 9 9 代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。
第一行两个整数代表矩阵大小 n n n 和 m m m。
接下来 n n n 行,每行一个长度为 m m m 的只含字符 0
到 9
的字符串,代表这个 n × m n \times m n×m 的矩阵。
一行一个整数代表细胞个数。
4 10
0234500067
1034560500
2045600671
0000000089
4
对于 100 % 100\% 100% 的数据,保证 1 ≤ n , m ≤ 100 1 \le n,m \le 100 1≤n,m≤100。
——————————————————————————————
这个题用的DFS
#include
#include
#include
#include
using namespace std;
const int N=110;
int g[N][N];
int n,m;
int ans;
void dfs(int a,int b)
{
if(a<1||a>n||b<1||b>m||g[a][b]==0)return ;//要有结束条件,不然死循环了
g[a][b]=0;
dfs(a-1,b);
dfs(a+1,b);
dfs(a,b-1);
dfs(a,b+1);
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
char k;
cin>>k;
if(k!='0')g[i][j]=1;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(g[i][j]==1)
{
ans++;
dfs(i,j);
}
}
}
printf("%d",ans);
return 0;
}
在峰会期间,武装部队得处于高度戒备。警察将监视每一条大街,军队将保卫建筑物,领空将布满了 F-2003 飞机。
此外,巡洋船只和舰队将被派去保护海岸线。不幸的是,因为种种原因,国防海军部仅有很少的几位军官能指挥大型海战。因此,他们培养了一些新海军指挥官。军官们选择了“海战”游戏来帮助他们学习。
在一个方形的盘上,放置了固定数量和形状的船只,每只船却不能碰到其它的船。在本题中,我们认为船是方形的,所有的船只都是由图形组成的方形。
求出该棋盘上放置的船只的总数。
第一行为两个整数 R R R 和 C C C,用空格隔开,分别表示游戏棋盘的行数和列数。
接下来 R R R 行,每行 C C C 个字符,为 #
或 .
。#
表示船只的一部分,.
表示水。
一行一个字符串,如果船的位置放得正确(即棋盘上只存在相互之间不能接触的方形,如果两个 #
号上下相邻或左右相邻却分属两艘不同的船只,则称这两艘船相互接触了)。就输出 There are S ships.
, S S S 表示船只的数量。否则输出 Bad placement.
。
6 8
.....#.#
##.....#
##.....#
.......#
#......#
#..#...#
There are 5 ships.
对于 100 % 100\% 100% 的数据, 1 ≤ R , C ≤ 1000 1 \le R,C \le 1000 1≤R,C≤1000。
——————————————————————————————
此题和第一题几乎一样,但是要注意拐角处
#include
#include
#include
#include
using namespace std;
const int N=1100;
int g[N][N];
int n,m;
int ans;
void dfs(int a,int b)
{
if(a<1||a>n||b<1||b>m||g[a][b]==0)return ;
g[a][b]=0;
dfs(a-1,b);
dfs(a+1,b);
dfs(a,b-1);
dfs(a,b+1);
}
bool check(int x,int y) //仅仅添加一个check函数
{
int cnt=0;
if(g[x][y]==1) cnt++;
if(g[x+1][y]==1) cnt++;
if(g[x][y+1]==1) cnt++;
if(g[x+1][y+1]==1) cnt++;
return cnt==3;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
char k;
cin>>k;
if(k!='.')g[i][j]=1;
}
}
for(int i=1;i<n;i++)
{
for(int j=1;j<m;j++)
{
if(check(i,j))
{
printf("Bad placement.");
return 0;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(g[i][j]==1)
{
ans++;
dfs(i,j);
}
}
}
printf("There are %d ships.",ans);
return 0;
}
你有一张某海域 N × N N \times N N×N 像素的照片,.
表示海洋、 #
表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......
其中 “上下左右” 四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 2 2 2 座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
.......
.......
.......
.......
....#..
.......
.......
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
第一行包含一个整数 N N N。 ( 1 ≤ N ≤ 1000 ) (1 \le N \le 1000) (1≤N≤1000)。
以下 N N N 行 N N N 列代表一张海域照片。
照片保证第 1 1 1 行、第 1 1 1 列、第 N N N 行、第 N N N 列的像素都是海洋。
一个整数表示答案。
7
.......
.##....
.##....
....##.
..####.
...###.
.......
1
时限 1 秒, 256M。蓝桥杯 2018 年第九届省赛
————————————————————————————
此题是蓝桥杯真题,此处用宽度优先搜索做一下
#include
#include
#include
#include
#include
using namespace std;
typedef pair<int,int> pii;
const int N=1010;
int n;
char g[N][N];
bool st[N][N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
void bfs(int a,int b,int &total,int &bound){
queue<pii> q;
q.push({a,b});
st[a][b]=true;
while(!q.empty()){
pii start=q.front();
q.pop();
total++;
bool is_bound=false;
for(int i=0;i<4;i++){
int x=start.first+dx[i],y=start.second+dy[i];
if(x<0||x>=n||y<0||y>=n)continue;
if(st[x][y])continue;
if(g[x][y]=='.'){
is_bound=true;
continue;
}
q.push({x,y});
st[x][y]=true;
}
if(is_bound)bound++;
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%s",g[i]);
}
int cnt=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(!st[i][j]&&g[i][j]=='#'){
int total=0,bound=0;
bfs(i,j,total,bound);
if(total==bound)cnt++;
}
}
}
printf("%d",cnt);
return 0;
}
谢谢~