当前位置: 首页 > news >正文

算法知识-15-深搜

一、概念

深度优先搜索(Deep First Search, DFS)是一种用于遍历或搜索树或图的算法。这种策略沿着树的深度遍历树的节点,尽可能深地搜索树的分支。

二、关键步骤

选择起点:根据题目要求,选择一个或多个节点作为搜索的起点。
递归搜索:从起点开始,递归地访问每个节点的所有未访问的邻接节点。
回溯:当到达一个节点,且这个节点没有未访问的邻接节点时,递归过程将回溯,尝试其他可能的路径。
记录状态:在递归前后,正确地记录和恢复状态(如访问状态、路径记录等)是非常重要的。

三、代码模板

以下题为例,说明关于深搜的几个模板
①看能不能到达
②能到达几次
③连通块,几个区域

1744 迷宫

有 1 个 n×n 的迷宫方格,在方格内“0”表示可以通行,“1”表示是障碍物不能通行,在(n,n)位置有一个宝箱。现在有个人在左上角( 1 , 1 )的位置,他在迷宫内可以向当前位置的上、下、左、右四个方向行走,能不能在迷宫里走到宝箱位置( n,n )。注意:测试数据保证起点和终点均为“0”,走的过程不能走出迷宫。

输入描述
输入第一行为 n(2 ≤n≤10 ),表示 n×n 的方格,接下来有 n 行,每行 n 个整数, 0 表示可以行走,1 表示不能行走,每个整数之间有个空格。

输出描述
如果可以走到终点,输出“YES”,否则输出“NO”

样例输入 1
3
0 0 1
1 0 0
0 1 0
样例输出 1
YES

题目分析:
首先我们输入,n,n行n列的数据【根据不同题目可能输入的数据存到字符串数组】
然后标记开始的位置【比如此题中开始位置就是 1,1,即一行一列的位置】,同时明确终点位置就是n,n【即n行n列】
然后开始搜索,构建搜索函数dfs,这个函数中,我们会走四个方向,所以使用两个一维数组表示四个方向坐标的改变的值
或者大家可以使用二维数组,我们还要构建一个标记数组,以下代码使用的是book数组来标记
函数中我们首先判断当前坐标是不是终点,如果是终点,就停止搜索【根据题目分析,有些题目不能终止,而是去计数】
然后再判断四个方向【不同题目,方向的数目不同】,计算新的落脚点
判断新的落脚点【nx,ny】是不是符合要求,此题中,需要满足三个条件①不越界;②没标记;③是可以通行的;
如果可以通行,则标记这个新的落脚点,继续下一步的搜索

#include<bits/stdc++.h>
using namespace std;
int n,a[15][15],dx[4]={-1,1,0,0},dy[4]={0,0,-1,1},book[15][15]; //左右上下 
bool flag;
void dfs(int x,int y){if(x == n && y == n){flag = true;return ;}for(int i=0;i<4;i++){int nx = x+dx[i],ny=y+dy[i];//出界   标记 if(nx>0&&nx<=n && ny>0&&ny<=n && book[nx][ny]==0 &&a[nx][ny]==0){book[nx][ny]=1;dfs(nx,ny);}}
}
int main(){cin >> n;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin >> a[i][j];}}book[1][1]=1;dfs(1,1);if(flag) cout<<"YES";else cout << "NO";return 0;
}

同样的,我们可以完成下面题目

2936 八个方向

已知山洞里面是由许多房间组成的迷宫,每个房间可以通往周围八个房间,迷宫大小是一个N*N的正方形,其中有一些蝙蝠堵路。现在从起始(1,1)的位置进入洞穴寻找宝藏(已有一个宝箱),如果可以找到宝藏输出YES,否则输出NO。

输入描述
第一行是一个正整数N(2<N ≤10),后面包含N*N行由0,1,2组成的矩阵,其中0表示可以走,1表示蝙蝠,2表示宝藏的位置。
(注意:第一个房间没有蝙蝠)

输出描述
一行,找到宝藏输出YES,否则输出NO 。

样例输入 1
6
0 0 1 1 0 0
1 0 0 1 0 0
0 0 0 1 2 0
0 1 1 1 0 0
0 0 0 1 0 0
0 0 0 1 0 0
样例输出 1
NO

样例输入 2
5
0 0 0 0 0
0 0 1 1 1
0 0 0 1 0
0 1 0 1 2
0 0 0 0 1
样例输出 2
YES

和迷宫的区别就是方向变多了

#include <bits/stdc++.h>
using namespace std;
int n,ex,ey,a[25][25],vis[105][105];
bool flag;
bool check(int nx,int ny){return nx>0&&nx<=n&&ny>0&&ny<=n&&vis[nx][ny]==0&&a[nx][ny]!=1;
}
int dx[8]={0,1,1,1,0,-1,-1,-1};//右,右下,下,左下,左,上,右上
int dy[8]={1,1,0,-1,-1,-1,0,1};//右,右下,下,左下,左,上,右上
void dfs(int x,int y){if(x==ex&&y==ey){//cout << x <<' '<< y;flag=1;return;}for(int i=0;i<8;i++){int nx=x+dx[i],ny=y+dy[i];if(check(nx,ny)){vis[nx][ny]=1;dfs(nx,ny);}}
}int main(){cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin>>a[i][j];if(a[i][j]==2) {ex=i;ey=j;}}}vis[1][1]=1;dfs(1,1);if(flag) cout<<"YES";else cout<<"NO";return 0;
}

3089 探索迷宫

水题,就不放题目了,自己找吧

#include <iostream>
using namespace std;
int n,m,x1,y1;
bool flag;
int vis[25][25];
int dx[4] = {1,0,-1,0},dy[4] = {0,1,0,-1};
int mp[25][25];
void dfs(int x,int y)
{if(x==x1 && y==y1){flag = 1;return ;}for(int i=0;i<4;i++){int nx = x+dx[i];int ny = y+dy[i];if(nx>0&&nx<=n&&ny>0&&ny<=m&&mp[nx][ny]!=1&&vis[nx][ny]==0){vis[nx][ny] = 1;dfs(nx,ny);}}}
int main() {cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>mp[i][j];}}if(mp[1][1]==1){cout<<"NO";return 0;}cin>>x1>>y1;vis[1][1] = 1;dfs(1,1);if(flag) cout<<"YES";else cout<<"NO";return 0;
}

3090 走迷宫

衍生版本,就是开始与结束位置也是自己输入的

#include<bits/stdc++.h>
using namespace std;
bool vis[105][105],f=0;
int n,x,y,startx,starty;
char c[105][105]; 
int dx[4] = {1,0,-1,0},dy[4] = {0,1,0,-1};
void dfs(int x1,int y1)
{if(x1==x && y1==y){f = 1;}for(int i=0;i<4;i++){int nx = x1+dx[i];int ny = y1+dy[i];if(nx>=0 && nx<n && ny>=0 && ny<n && vis[nx][ny]==0 && c[nx][ny]=='.'){vis[nx][ny] = 1;dfs(nx,ny);}}
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n;for(int i=0;i<n;i++){for(int j=0;j<n;j++){cin>>c[i][j];}}cin>>startx>>starty>>x>>y;if(c[startx][starty]=='#' or c[x][y]=='#'){cout<<"no";return 0;}else{dfs(startx,starty);}if(f==1) cout<<"yes";else cout<<"no";return 0;
}

2936 八个方向

水题++,只有方向变多了,大家注意这个方向的数组一定要正确【此题copy杨同学的代码】

#include <bits/stdc++.h>
using namespace std;
int n,ex,ey,a[25][25],vis[105][105];
bool flag;
bool check(int x,int y){return x>=1&&x<=n&&y>=1&&y<=n&&!vis[x][y]&&a[x][y]!=1;
}
int dx[8]={-1,0,1,1,1,0,-1,-1},dy[8]={1,1,1,0,-1,-1,-1,0};
void dfs(int x,int y){if(x==ex&&y==ey){flag=1;return;}for(int i=0;i<8;i++){int nx=x+dx[i],ny=y+dy[i];if(check(nx,ny)){vis[nx][ny]=1;dfs(nx,ny);}}
}int main(){cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin>>a[i][j];if(a[i][j]==2){ex=i;ey=j;}}}if(a[1][1]==1){cout<<"NO";return 0;}vis[1][1]=1;dfs(1,1);if(flag) cout<<"YES";else cout<<"NO";return 0;
}

4143 中国象棋的马

做完八个方向,来看看这个,八个方向的衍生版本
在这里插入图片描述
不懂就看上图,再不懂?就微信私聊吧,啥也别说了

#include <bits/stdc++.h>
using namespace std;
int n,m,ex,ey,a[25][25],vis[105][105];
bool flag;
bool check(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y]&&a[x][y]!=1;
}
int dx[8]={-1,-2,-2,-1,1,2,2,1},dy[8]={2,1,-1,-2,-2,-1,1,2};
void dfs(int x,int y){if(x==ex&&y==ey){flag=1;return;}for(int i=0;i<8;i++){int nx=x+dx[i],ny=y+dy[i];if(check(nx,ny)){vis[nx][ny]=1;dfs(nx,ny);}}
}int main(){cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>a[i][j];}}cin>>ex>>ey;if(a[1][1]==1){cout<<"NO";return 0;}vis[1][1]=1;dfs(1,1);if(flag) cout<<"YES";else cout<<"NO";return 0;
}

说完这一类的题目,我们接下来看看统计线路相关的题目

2937 八个方向统计线路

已知山洞里面是由许多房间组成的迷宫,每个房间可以通往周围八个房间,迷宫大小是一个N*N的正方形,其中有一些蝙蝠堵路。现在从起始(1,1)的位置进入洞穴寻找宝藏(只有一个宝箱),统计有多少条线路可以找到宝藏。

输入描述
第一行是一个正整数N(2<N<6),后面包含N*N行由0,1,2组成的矩阵,其中0表示可以走,1表示蝙蝠,2表示宝藏的位置。

输出描述
一行,一个整数,表示可以找到宝藏的线路。

样例输入 1
6
0 0 1 1 0 0
1 0 0 1 0 0
0 0 0 1 2 0
0 1 1 1 0 0
0 0 0 1 0 0
0 0 0 1 0 0
样例输出 1
0

样例输入 2
2
0 0
0 2
样例输出 2
5

思路分析:这个题目,不是找一次终点,而是多次找终点,所以被归为一类的题目
这个题目的核心代码是

            vis[nx][ny]=1;dfs(nx,ny);vis[nx][ny]=0;

就是我们标记当前位置搜索完毕后要把当前位置给去除标记再次搜索,看看有没有别的可能到达终点
代码如下【来自杨同学,后续不说明了哈】

// 来自杨同学,我就不写了,后面大抵都是他的代码,他把判断内容用check函数封装了
#include <bits/stdc++.h>
using namespace std;
int n,ex,ey,a[105][105],vis[105][105],sum;
bool check(int x,int y){return x>=1&&x<=n&&y>=1&&y<=n&&!vis[x][y]&&a[x][y]!=1;
}
int dx[8]={-1,0,1,1,1,0,-1,-1},dy[8]={1,1,1,0,-1,-1,-1,0};
void dfs(int x,int y){if(x==ex&&y==ey){sum++;return;}for(int i=0;i<8;i++){int nx=x+dx[i],ny=y+dy[i];if(check(nx,ny)){vis[nx][ny]=1;dfs(nx,ny);vis[nx][ny]=0;}}
}
int main(){cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin>>a[i][j];if(a[i][j]==2){ex=i;ey=j;}}}if(a[1][1]==1){cout<<0;return 0;}vis[1][1]=1;dfs(1,1);cout<<sum;return 0;
}

2935 统计线路

水++

//这个风格是邢同学的
#include<bits/stdc++.h>
using namespace std;
int vis[11][11],ans,n;
int mp[11][11];
int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};
void dfs(int x,int y)
{if(mp[x][y]==2){ans++;return ;}	for(int i=0;i<4;i++){int nx = x+dx[i];int ny = y+dy[i];if(nx>0&&nx<=n&ny>0&&ny<=n&&vis[nx][ny]==0&&mp[nx][ny]!=1){vis[nx][ny] = 1;dfs(nx,ny);vis[nx][ny] = 0;}}
} 
int main()
{cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin>>mp[i][j];}}vis[1][1] = 1;dfs(1,1);cout<<ans;return 0;
}

1353 围成面积 **

这个题就好玩了
编程计算由数字1围成的下列图形的面积。面积计算方法是统计数字1所围成的闭合曲线中点的数目。如下图所示,在10 * 10的二维数组中,有数字1围住了15个点,因此面积为15。
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 0 0 1 0 0
0 0 0 0 0 1 0 0 1 0
0 0 1 0 0 0 1 0 1 0
0 1 0 1 0 1 0 0 1 0
0 1 0 0 1 1 0 1 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0

输入描述
输入一个包含 0 和 1 数字的 10∗10 矩阵
输出描述
输出面积

样例输入 1
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 0 0 1 0 0
0 0 0 0 0 1 0 0 1 0
0 0 1 0 0 0 1 0 1 0
0 1 0 1 0 1 0 0 1 0
0 1 0 0 1 1 0 1 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0
样例输出 1
15

分析一下:这个题要看1围起来的0的个数,我们要把这个题的数据分三部分,外层0,中层1,内层0,一共是10行10列,除去外层能搜索到的0的个数,输入时判断累加的1的个数,不就是中间的0的个数
上图
在这里插入图片描述
不理解的直接来找我

#include <bits/stdc++.h>
using namespace std;
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
int a[105][105],sum1,sum2,ans;
bool flag;
bool check(int x,int y){return x>=1&&x<=10&&y>=1&&y<=10&&a[x][y]!=1;
}
void dfs(int x,int y){a[x][y]=1;for(int i=0;i<=3;i++){int nx=x+dx[i],ny=y+dy[i];if(check(nx,ny)){sum2++;dfs(nx,ny);}}
}
int main(){for(int i=1;i<=10;i++){for(int j=1;j<=10;j++){cin>>a[i][j];if(a[i][j]==1) sum1++;}}for(int i=1;i<=10;i++){for(int j=1;j<=10;j++){if(a[i][j]==0){sum2++;dfs(i,j);flag=1;break;}}if(flag) break;}ans=100-sum1-sum2;cout<<ans;return 0;
}

6604 地图找车

水++

#include <bits/stdc++.h>
using namespace std;
char a[105][105];
int n,m,ex,ey,vis[105][105];
bool flag;
bool check(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y]&&a[x][y]!='X';
}
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
void dfs(int x,int y){if(x==ex&&y==ey){flag=1;return;}for(int i=0;i<4;i++){int nx=x+dx[i],ny=y+dy[i];if(check(nx,ny)){vis[nx][ny]=1;dfs(nx,ny);}}
}int main(){cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>a[i][j];if(a[i][j]=='*'){ex=i;ey=j;}}}if(a[1][1]=='X'){cout<<"NO";return 0;}vis[1][1]=1;dfs(1,1);if(flag) cout<<"YES";else cout<<"NO";return 0;
}

2929 寻宝

侠盗 Hank 经过千难万险终于来到了恶人岛,为了拿到恶人岛的宝座去帮助穷人,Hank 先对恶人岛进行了侦查,发现恶人岛有一个迷阵,宝藏摆在了迷阵的深处。迷阵由 M×N 个方 格组成,有的方格内有可以发现 Hank 的守卫,而有的方格内则是安全。为了展现自己的实 力,Hank 决定不仅要拿走恶人岛的宝藏,还要给他们留一封信,告诉恶人自己有 g 种方法 找到宝藏。现在要求你来帮助他实现这个目标。
迷阵越大,守卫越多。

输入描述

输入有一组测试数据,以两个非零整数 N 和 M 开始,两者均不大于20。N表示迷阵行数, M表示迷阵列数。接下来有 N 行, 每行包含 M 个字符,不同字符分别代表不同含义:

‘@’:Hank 所在的位置;
‘.’:可以安全通行的方格;
‘#’:有守卫的方格;
‘*’:宝藏所在位置。
输出描述

一个整数 g,表示 Hank 有 g 种方法可以找到宝藏。如果他不可能找到宝藏, 则输出-1。

样例输入 1

8 8
.@##…#
#…#.#
#.#.##…
…#.###.
#.#…#.
…###.#.
…#.*…
.#…###
样例输出 1

4
样例输入 2

9 6
.#…#.
.#.*.#
.####.
…#…
…#…
…#…
…#…
#.@.##
.#…#.
样例输出 2

-1

思路:水题,就是多个判断

#include <bits/stdc++.h>
using namespace std;
char a[105][105];
int n,m,fx,fy,ex,ey,vis[105][105],sum;
bool flag;
bool check(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y]&&a[x][y]!='#';
}
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
void dfs(int x,int y){if(x==ex&&y==ey){flag=1;sum++;return;}for(int i=0;i<4;i++){int nx=x+dx[i],ny=y+dy[i];if(check(nx,ny)){vis[nx][ny]=1;dfs(nx,ny);vis[nx][ny]=0;}}
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>a[i][j];if(a[i][j]=='@'){fx=i;fy=j;}if(a[i][j]=='*'){ex=i;ey=j;}}}vis[fx][fy]=1;dfs(fx,fy);if(!flag) cout<<-1;else cout<<sum;return 0;
}

1791 多少块水洼

有一块 N×M 的土地,雨后积起了水,有水标记为‘W’,干燥为‘.’。八连通的积水被认为是连接在一起的。请求出院子里共有多少水洼?

输入描述

第一行为 N,M (1≤N,M≤100)。
下面为 N×M的土地示意图。

输出描述

一行,共有的水洼数。

样例输入 1

10 12
W…WW.
.WWW…WWW
…WW…WW.
…WW.
…W…
…W…W…
.W.W…WW.
W.W.W…W.
.W.W…W.
…W…W.
样例输出 1

3

思路:从每个点搜索,并且标记,如果搜索停止,就看下个点搜索的情况。看最后能搜索到几个区域,记得计数

#include<bits/stdc++.h>
using namespace std;
int vis[105][105];
char mp[105][105];
int n,m,ans;
int dx[8] = {0,1,1,1,0,-1,-1,-1};
int dy[8] = {1,1,0,-1,-1,-1,0,1};
void dfs(int x,int y)
{for(int i=0;i<8;i++){int nx = x+dx[i];int ny = y+dy[i];if(nx>=0 && nx<n && ny>=0 && ny<m && mp[nx][ny]=='W' && vis[nx][ny]==0){vis[nx][ny] = 1;dfs(nx,ny);}}
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n>>m;for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>mp[i][j];}}for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(mp[i][j]=='W'&& vis[i][j]==0){ans++;vis[i][j] = 1;dfs(i,j);}}}cout<<ans;return 0;
}

1852 连通块

一个 n×m 的方格图,一些格子被涂成了黑色,在方格图中被标为 1,白色格子标为 0。问有多少个四连通的黑色格子连通块。四连通的黑色格子连通块指的是一片由黑色格子组成的区域,其中的每个黑色格子能通过四连通的走法(上下左右),只走黑色格子,到达该连通块中的其它黑色格子。

输入描述

第一行两个整数 n,m,表示一个 n×m 的方格图。
接下来 n 行,每行 m 个整数,分别为 0 或 1,表示这个格子是黑色还是白色。

输出描述

一行一个整数 ans,表示图中有 ans 个黑色格子连通块。

样例输入 1

3 3
1 1 1
0 1 0
1 0 1
样例输出 1

3
提示

数据范围与提示
1≤n,m≤100

#include <bits/stdc++.h>
using namespace std;
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
int n,m,a[105][105],sum;
bool check(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m&&a[x][y]!=0;
}
void dfs(int x,int y){a[x][y]=0;for(int i=0;i<=3;i++){int nx=x+dx[i],ny=y+dy[i];if(check(nx,ny)){dfs(nx,ny);}}
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>a[i][j];}}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(a[i][j]!=0){sum++;dfs(i,j);}}}cout<<sum;return 0;
}

6611 吃蛋糕

小童今天跟家人一起吃生日蛋糕庆祝生日,这块蛋糕是由n×m 的网格构成,每个网格上面都放有不同的水果。小童把这些水果分为两类,一类是自己喜欢吃的水果,用’#‘来表示;一类是自己不喜欢吃的水果,用’.'来表示。小童能吃到几块只包含自己喜欢吃的水果?一块蛋糕为上下左右为#的连通区域。

输入描述

第一行为两整数 n,m ,表示矩阵的大小为n×m(0<m,n≤100)。
从第二行开始是一个 n×m 的矩阵。

输出描述

一行,表示蛋糕块数

样例输入 1

4 5
.#.#.
.#.##
.##…
#…
样例输出 1

3

#include<bits/stdc++.h>
using namespace std;
int n,m;
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};
int ans;
bool vis[105][105];
char g[105][105];
void dfs(int x,int y){for(int i=0;i<4;i++){int nx = x+dx[i];int ny = y+dy[i];if(nx>0 && nx<=n && ny>0 && ny<=m && g[nx][ny]=='#' && vis[nx][ny]==0){vis[nx][ny] = 1;dfs(nx,ny);}}
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>g[i][j];}}for(int i=1;i<=n;i++){for(int  j=1;j<=m;j++){if(g[i][j]=='#'&& vis[i][j]==0){ans++;vis[i][j] = 1;dfs(i,j);}}}cout<<ans;return 0;
}

6624 数地图连通块面积

#include<bits/stdc++.h>
using namespace std;
int n,m;
bool f;
int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};
int ans;
bool vis[105][105];
char g[105][105];
void dfs(int x,int y){for(int i=0;i<4;i++){int nx = x+dx[i];int ny = y+dy[i];if(nx>0 && nx<=n && ny>0 && ny<=m && g[nx][ny]=='#' && vis[nx][ny]==0){vis[nx][ny] = 1;ans++;dfs(nx,ny);}}
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>g[i][j];}}for(int i=1;i<=n;i++){for(int  j=1;j<=m;j++){if(g[i][j]=='#'&& vis[i][j]==0){vis[i][j] = 1;dfs(i,j);cout<<ans+1<<" ";ans = 0;f = 1;}}}if(f==0){cout<<-1;}return 0;
}

6822 红与黑

第一行是两个整数 n 和 m,表示房间是 n 行 m 列大小。在接下来的 n 行中,每行包括 m 个字符。每个字符表示一块瓷砖的颜色,规则如下:

‘.’:黑色的瓷砖;
‘#’:红色的瓷砖;
‘@’:黑色的瓷砖,并且你站在这块瓷砖上。该字符在数据中出现一次。
输出描述

一行,显示你从初始位置出发能到达的瓷砖数(注意:记数时包括初始位置的瓷砖)。

样例输入 1

5 6
…#.
…#

#@…#
.#…#.
样例输出 1

21
提示

数据范围与提示
1<n,m<20
注意此题中初始位置就是一个黑色区域,要计数

#include <bits/stdc++.h>
using namespace std;
char a[105][105];
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
int n,m,sum;
bool check(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m&&a[x][y]!='#';
}
void dfs(int x,int y){a[x][y]='#';for(int i=0;i<=3;i++){int nx=x+dx[i],ny=y+dy[i];if(check(nx,ny)){sum++;dfs(nx,ny);}}
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>a[i][j];}}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(a[i][j]=='@'){sum++;dfs(i,j);break;}}}cout<<sum;return 0;
}

相关文章:

算法知识-15-深搜

一、概念 深度优先搜索&#xff08;Deep First Search, DFS&#xff09;是一种用于遍历或搜索树或图的算法。这种策略沿着树的深度遍历树的节点&#xff0c;尽可能深地搜索树的分支。 二、关键步骤 选择起点&#xff1a;根据题目要求&#xff0c;选择一个或多个节点作为搜索…...

区块链dapp 开发详解(VUE3.0)

1、安装metamask 插件。 2、使用封装的工具包: wagmi . 3、 wagmi 操作手册地址:connect | Wagmi 4、注意事项&#xff1a; 因为最初是react 版本&#xff0c;所以在VUE版的官方文档有很多地方在 import 用的是 wagmi,需要改为 wagmi/vue 。 连接成功后打印的内容如下&…...

Plugin [id: ‘flutter‘] was not found in any of the following sources解决方法

文章目录 错误描述解决方法修正方案&#xff1a;继续使用 apply from修正后的 build.gradle说明警告的处理进一步验证 错误描述 Plugin [id: ‘flutter’] was not found in any of the following sources: Gradle Core Plugins (not a core plugin, please see https://docs…...

专升本-高数 1

第 0 章&#xff0c;基础知识 一&#xff0c;重要公式 1、完全平方 (ab)a2abb (a-b)a-2abb 2、平方差公式 &#xff08;a-b&#xff09;(ab)a-b 3、立方差公式 a-b(a-b)(aabb) 4、 立方和公式 ab(ab)(a-abb) 二&#xff0c;基本初等函数 1&#xff0c;幂函数 一元二…...

【考前预习】3.计算机网络—数据链路层

往期推荐 【考前预习】2.计算机网络—物理层-CSDN博客 【考前预习】1.计算机网络概述-CSDN博客 浅谈云原生--微服务、CICD、Serverless、服务网格_云原生cicd-CSDN博客 子网掩码、网络地址、广播地址、子网划分及计算_子网广播地址-CSDN博客 浅学React和JSX-CSDN博客 目录 1.数…...

DockeUI 弱口令登录漏洞+未授权信息泄露

0x01 产品描述: DockerUI是一款开源的、强大的、轻量级的Docker管理工具。DockerUI覆盖了 docker cli 命令行 95% 以上的命令功能,通过可视化的界面,即使是不熟悉docker命令的用户也可以非常方便的进行Docker和Docker Swarm集群进行管理和维护。0x02 漏洞描述: DockerUI中存…...

【电子元器件】电感基础知识

本文章是笔者整理的备忘笔记。希望在帮助自己温习避免遗忘的同时&#xff0c;也能帮助其他需要参考的朋友。如有谬误&#xff0c;欢迎大家进行指正。 一、 电感的基本工作原理 1. 电感的基本工作原理如下&#xff1a; &#xff08;1&#xff09; 当线圈中有电流通过时&#…...

【SSH+X11】VsCode使用Remote-SSH在远程服务器的docker中打开Rviz

&#x1f680;今天来分享一下通过VsCode的Remote-SSH插件在远程服务器的docker中打开Rviz进行可视化的方法。 具体流程如下图所示&#xff0c;在操作开始前&#xff0c;请先重启设备&#xff0c;排除之前运行配置的影响&#xff1a; ⭐️ 我这里是使用主机连接服务器&#xff…...

Vue Web开发(五)

1. axios axios官方文档 异步库axios和mockjs模拟后端数据&#xff0c;axios是一个基于promise的HTTP库&#xff0c;使用npm i axios。在main.js中引入&#xff0c;需要绑定在Vue的prototype属性上&#xff0c;并重命名。   &#xff08;1&#xff09;main.js文件引用 imp…...

HarmonyOS:使用Grid构建网格

一、概述 网格布局是由“行”和“列”分割的单元格所组成&#xff0c;通过指定“项目”所在的单元格做出各种各样的布局。网格布局具有较强的页面均分能力&#xff0c;子组件占比控制能力&#xff0c;是一种重要自适应布局&#xff0c;其使用场景有九宫格图片展示、日历、计算器…...

开源Java快速自测工具,可以调用系统内任意一个方法

java快速测试框架&#xff0c;可以调到系统内任意一个方法&#xff0c;告别写单测和controller的困扰。 开源地址&#xff1a;https://gitee.com/missyouch/Easy-JTest 我们在开发时很多时候想要测试下自己的代码&#xff0c;特别是service层或者是更底层的代码&#xff0c;就…...

力扣刷题TOP101: 29.BM36 判断是不是平衡二叉树

目录&#xff1a; 目的 思路 复杂度 记忆秘诀 python代码 目的&#xff1a; 输入一棵节点数为 n 二叉树&#xff0c;判断该二叉树是否是平衡二叉树。 思路 什么是平衡二叉树&#xff08;AVL 树&#xff09;&#xff1f; 每个节点的左子树和右子树的高度差不能超过 1。确保…...

【在Linux世界中追寻伟大的One Piece】自旋锁

目录 1 -> 概述 2 -> 原理 3 -> 优缺点及使用场景 3.1 -> 优点 3.2 -> 缺点 3.3 -> 使用场景 4 -> 纯软件自旋锁类似的原理实现 4.1 -> 结论 5 -> 样例代码 1 -> 概述 自旋锁是一种多线程同步机制&#xff0c;用于保护共享资源避免受并…...

前端编辑器JSON HTML等,vue2-ace-editor,vue3-ace-editor

与框架无关 vue2-ace-editor有问题&#xff0c;ace拿不到&#xff08;brace&#xff09; 一些组件都是基于ace-builds或者brace包装的 不如直接用下面的&#xff0c;不如直接使用下面的 <template><div ref"editor" class"json-editor"><…...

C++ 中的运算符重载

运算符重载是C中的一种特性&#xff0c;它允许开发者为自定义类型定义或改变标准运算符的行为。通过运算符重载&#xff0c;你可以使得用户定义的类像内置类型一样使用运算符&#xff0c;比如加法、减法、赋值等。 如何在C中进行运算符重载&#xff1f; 重载运算符的语法&#…...

渗透测试工具 -- SQLmap安装教程及使用

随着网络安全问题日益严峻&#xff0c;渗透测试成为了保护信息安全的重要手段。而在渗透测试的众多工具中&#xff0c;SQLmap凭借其强大的自动化SQL注入检测和利用能力&#xff0c;成为了网络安全专家必备的利器。那么&#xff0c;你知道如何高效地使用SQLmap进行漏洞扫描吗&am…...

使用 Database Tools 实现高效数据查询的十大 IntelliJ IDEA 快捷键

得益于 IntelliJ IDEA Ultimate 的 Database Tools&#xff08;数据库工具&#xff09;中的专用 SQL 查询控制台&#xff0c;您无需离开 IDE 即可轻松修改连接到您的 Java 应用程序的任何数据库中的数据&#xff0c;以及从这些数据库中提取数据。 查询控制台具有 SQL 语句特定的…...

SpringBoot 整合 RabbitMQ 实现流量消峰

RabbitMQ 即一个消息队列&#xff0c;主要是用来实现应用程序的异步和解耦&#xff0c;同时也能起到消息缓冲&#xff0c;消息分发的作用。 消息中间件在互联网公司的使用中越来越多&#xff0c;刚才还看到新闻阿里将 RocketMQ 捐献给了 Apache&#xff0c;当然了今天的主角还…...

大数据挖掘建模平台案例分享

大数据挖掘建模平台是由泰迪自主研发&#xff0c;面向企业级用户的大数据挖掘建模平台。平台采用可视化操作方式&#xff0c;通过丰富内置算法&#xff0c;帮助用户快速、一站式地进行数据分析及挖掘建模&#xff0c;可应用于处理海量数据、高复杂性的数据挖掘任务&#xff0c;…...

MySQL数据表的管理

1.创建表 语法&#xff1a; create table 表名( 字段名 字段里保存数据的类型【(数据的长度) 约束】, 字段名 字段里保存数据的类型【(数据的长度) 约束】, 字段名 字段里保存数据的类型【(数据的长度) 约束】 ...... ); 注意&#xff1a;数据类型和约束&#xff0c;接下来用…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...