DFS(深度优先搜索)是一种图遍历算法,用于遍历或搜索树或图的算法。该算法从起点开始,沿着一条路径一直走到底,直到无法继续为止,然后回溯到前一个节点,再沿着另一条路径继续搜索,直到遍历完所有节点为止。
在DFS算法中,通常使用递归或栈来实现。当使用递归实现时,该算法会不断地递归调用自身,直到遍历到最深的节点为止。当使用栈实现时,该算法会将当前节点入栈,然后遍历该节点的邻居节点,如果邻居节点没有被访问过,就将其入栈,直到遍历完所有节点。
DFS算法可以用于解决很多问题,如图的连通性问题、拓扑排序、迷宫问题等。它的时间复杂度为O(V+E),其中V表示节点数,E表示边数。
BFS(广度优先搜索)是一种图遍历算法,用于遍历或搜索树或图的算法。该算法从起点开始,先访问起点的所有邻居节点,然后依次访问邻居节点的所有邻居节点,直到遍历完所有节点为止。
在BFS算法中,通常使用队列来实现。首先将起点节点入队,然后从队列中取出一个节点,访问该节点的所有邻居节点,并将邻居节点入队,直到队列为空为止。
BFS算法可以用于解决很多问题,如图的连通性问题、最短路径问题、迷宫问题等。它的时间复杂度为O(V+E),其中V表示节点数,E表示边数。
以下是我做的一些习题,加强对二种算法的理解。
这道题可以使用DFS或BFS算法来求解。以下是DFS算法的思路:
-
找到闭合圈的起点,可以从第一行或第一列开始,遍历到第一个为0的位置。
-
从起点开始进行DFS遍历,将遍历到的点标记为已访问,并将其填充为2。
-
对于每个已访问的点,遍历其四个方向的相邻点,如果相邻点为0且未访问,则递归访问该相邻点,并将其填充为2。
-
如果遍历到一个点的四个方向都是已访问或已经到达了闭合圈的终点,则返回上一级递归。
-
遍历完闭合圈内的所有区域后,输出填充后的方阵。
以下是dfs实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int a[32][32],b[32][32];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
int n,i,j;
void dfs(int p,int q){
int i;
if (p<0||p>n+1||q<0||q>n+1||a[p][q]!=0)
return;
a[p][q]=1;
for (i=0;i<4;i++)
dfs(p+dx[i],q+dy[i]);
}
int main(){
scanf("%d",&n);
for (i=1;i<=n;i++)
for (j=1;j<=n;j++){
scanf("%d",&b[i][j]);
if (b[i][j]==0) a[i][j]=0;
else a[i][j]=1;
}
dfs(0,0);
for (i=1;i<=n;i++){
for (j=1;j<=n;j++){
if (a[i][j]==0)
printf("2 ");
else
printf("%d ",b[i][j]);
}
printf("\n");
}
}
下一道题
这道题可以使用DFS或BFS算法来求解。以下是DFS算法的思路:
-
从起点开始进行DFS遍历,将遍历到的点标记为已访问,并统计从起点到该点的路径总数。
-
对于每个已访问的点,遍历其四个方向的相邻点,如果相邻点不是障碍且未访问,则递归访问该相邻点,并将其路径总数加上当前点的路径总数。
-
如果遍历到终点,则返回当前点的路径总数。
-
如果遍历到一个点的四个方向都是已访问或是障碍,则返回0。
-
最终统计从起点到终点的路径总数并输出。
以下是dfs实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int n,m,t,p,q;
int sum = 0;
int a[51][51],book[51][51];
void dfs(int x,int y,int step){
int next[4][2] = {
{0,1},//向右走
{1,0},//向下走
{0,-1},//向左走
{-1,0}//向上走
};
int tx,ty,k;
if(x==p&&y==q){
sum++;
return;
}
for(k=0;k<=3;k++){
tx = x+next[k][0];
ty = y+next[k][1];
if(tx<1||tx>n||ty<1||ty>m){
continue;
}
if(a[tx][ty]==0&&book[tx][ty]==0){
book[tx][ty] = 1;
dfs(tx,ty,step+1);
book[tx][ty] = 0;
}
}
return;
}
int main(){
int i,j,startx,starty;
scanf("%d %d %d",&n,&m,&t);
// for(i=1;i<=n;i++){
// for(j=1;j<=m;j++){
// scanf("%d",&a[i][j]);
// }
// }
scanf("%d %d %d %d",&startx,&starty,&p,&q);
int g,h;
for(i=1;i<=t;i++){
scanf("%d %d",&g,&h);
book[g][h] = 1;
}
book[startx][starty] = 1;
dfs(startx,starty,0);
printf("%d",sum);
//getchar();getchar();
return 0;
}
下一道题
这道题可以使用BFS算法来求解。以下是BFS算法的思路:
-
创建一个标记数组dist,dist[i][j]表示马从起点(x,y)到达点(i,j)的最短步数,初值为-1。
-
创建一个队列queue,将起点(x,y)加入队列。
-
从队列中取出一个点(u,v),遍历其可以到达的八个点(x,y),如果点(x,y)未被访问过,则将其加入队列,并更新dist[x][y]的值为dist[u][v]+1。
-
重复步骤3,直到队列为空为止。
-
输出dist数组。
以下是bfs实现
#include <stdio.h>
#include <string.h>
#define MAX_N 1001
int n, m, x, y;
int dx[] = {-1, -2, -2, -1, 1, 2, 2, 1};
int dy[] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dist[MAX_N][MAX_N];
int queue[MAX_N * MAX_N][2];
void bfs()
{
memset(dist, -1, sizeof(dist));
int head = 0, tail = 1;
queue[0][0] = x, queue[0][1] = y;
dist[x][y] = 0;
while (head < tail) {
int x0 = queue[head][0], y0 = queue[head][1];
head++;
for (int i = 0; i < 8; i++) {
int x1 = x0 + dx[i], y1 = y0 + dy[i];
if (x1 >= 1 && x1 <= n && y1 >= 1 && y1 <= m && dist[x1][y1] == -1) {
dist[x1][y1] = dist[x0][y0] + 1;
queue[tail][0] = x1, queue[tail][1] = y1;
tail++;
}
}
}
}
int main()
{
if (scanf("%d%d%d%d", &n, &m, &x, &y) != 4) return 1;
bfs();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
printf("%-5d", dist[i][j]);
}
printf("\n");
}
return 0;
}
下一题
这道题可以使用DFS算法来求解。以下是DFS算法的思路:
-
创建一个数组,这个数组表示第i个食材是否已经被选中,初值为false。
-
创建两个变量,分别表示当前已选配料的酸度总和和苦度总和。
-
创建一个变量min,表示可能的总酸度和总苦度的最小绝对差,初值为无穷大。
-
从第一个食材开始,遍历所有可选食材,如果当前食材未被选中,则将其加入当前配料,更更新两个变量的值,改变数组标记。
-
如果当前配料已经包含所有可选食材,则计算两个变量的绝对差,更新min的值。
-
否则,递归调用dfs函数,继续选取下一个食材。
-
回溯时,将当前食材从配料中移除,更新两个变量的值,改变数组标记。
-
重复步骤4~7,直到遍历完所有可选食材为止。
-
输出min的值。
以下是dfs算法实现
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAX_N 15
int n;
int s[MAX_N], b[MAX_N];
int ans = INT_MAX;
void dfs(int u, int ss, int bb) {
if (u == n) {
if (ss != 1) ans = ans < abs(ss - bb) ? ans : abs(ss - bb);
return;
}
dfs(u + 1, ss, bb);
dfs(u + 1, ss * s[u], bb + b[u]);
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d%d", &s[i], &b[i]);
}
dfs(0, 1, 0);
printf("%d\n", ans);
return 0;
}
以上就是本期内容。dfs和bfs的作用远不止如此,二叉树的遍历也能使用,关注我,为你更新。