一、BFS通用模板
BFS是广度优先搜索。适用于最短路径、最小步数、层序遍历、连通块计数
网格图模拟BFS:给定一个二维网格,以及一些初始位置,并说明初始位置的蔓延条件,最后求一些计数或者最值问题。
思路:通过队列q存储位置。初始值即为初始位置,每次考虑当前位置(x,y)的四周,尝试蔓延。
python
from collections import deque
# 迷宫类 BFS 模板(网格)
def bfs_grid(start, end, grid):
n = len(grid)
m = len(grid[0])
# 方向数组:上下左右
dirs = [(-1,0), (1,0), (0,-1), (0,1)]
# 访问标记/距离数组
dist = [[-1]*m for _ in range(n)]
q = deque()
# 初始化起点
sx, sy = start
dist[sx][sy] = 0
q.append((sx, sy))
while q:
x, y = q.popleft()
# 到达终点,直接返回最短距离
if (x, y) == end:
return dist[x][y]
# 遍历四个方向
for dx, dy in dirs:
nx = x + dx
ny = y + dy
# 边界判断 + 未访问 + 可通行
if 0 <= nx < n and 0 <= ny < m and dist[nx][ny] == -1 and grid[nx][ny] == 0:
dist[nx][ny] = dist[x][y] + 1
q.append((nx, ny))
# 无法到达
return -1
题目描述
输入描述
输出描述
输入输出示例
输入
4 5
.g...
.....
..g..
.....
2
输出
gggg.
gggg.
ggggg
.ggg.
python
# 输入地图的行数和列数
n, m = map(int, input().split())
# 初始化一个空的地图列表
Map = []
# 根据输入的行数和列数,逐行读取地图数据并添加到Map列表中
for _ in range(n):
Map.append(list(input()))
# 输入需要进行的bfs次数
k = int(input())
# 初始化一个空队列,用于存储起点坐标
q = []
# 遍历整个地图,将所有起点(标记为'g')的坐标加入队列
for i in range(n):
for j in range(m):
if Map[i][j] == 'g':
q.append((i, j))
# 定义一个函数,用于检查给定的坐标是否在地图范围内且是可以通过的(标记为'.')
def check(x, y):
if 0 <= x < n and 0 <= y < m and Map[x][y] == '.':
return True
return False
# 定义bfs函数
def bfs():
global q # 声明q为全局变量,以便在函数内部修改
cnt = len(q) # 初始化计数器,记录当前队列中的元素数量
while cnt > 0:
x, y = q.pop(0) # 取出队列中的第一个元素(坐标)
# 遍历四个方向(上、下、左、右)
for dx, dy in [[-1, 0], [1, 0], [0, -1], [0, 1]]:
cx, cy = dx + x, dy + y # 计算新的坐标
# 如果新坐标在地图范围内且是可以通过的
if check(cx, cy):
# 将新坐标加入队列
q.append((cx, cy))
# 标记新坐标已经访问过
Map[cx][cy] = 'g'
cnt -= 1 # 计数器减一
# 执行k次bfs操作
for i in range(k):
bfs()
# 输出最终的地图
for i in Map:
print(''.join(i))
题目描述
输入描述
输出描述
输出一个整数表示答案。
输入输出示例
输入
7
.......
.##....
.##....
....##.
..####.
...###.
.......
输出
1
python
#_________________________________________________________ BFS
N=int(input())
Map=[list(input()) for _ in range(N)]
directions=[[-1,0],[1,0],[0,-1],[0,1]]
visited=[[0]*N for _ in range(N)]
# 问题二flag 没有在每个岛重置
flag=True
q=[]
def bfs():
#问题一BFS 只处理了一个点
# x,y=q.pop(0)
# 默认会被淹没
global flag
# 队列不为空
while q:
x,y=q.pop(0)
# 找到满足条件的情况
if Map[x-1][y]=='#' and Map[x+1][y]=='#' and Map[x][y-1]=='#' and Map[x][y+1]=='#':
flag=False
# 问题三这个岛剩下的点 visited 没标记
# return
for dx,dy in directions:
cx=dx+x
cy=dy+y
if 0<=cx<N and 0<=cy<N and Map[cx][cy]=='#' and visited[cx][cy]==0:
visited[cx][cy]=1
q.append((cx,cy))
ans=0
for i in range(N):
for j in range(N):
flag=True
# 访问起始点
if Map[i][j]=='#' and visited[i][j]==0:
visited[i][j]=1
q.append((i,j))
bfs()
# 会被淹没
if flag:
ans+=1
print(ans)
二、DFS通用模板
DFS:深度优先搜索。适用于:迷宫最短路径、最小步数、层序遍历、连通块
递归调用函数查找
python
# 迷宫类 DFS 模板(网格)
visited = set() # 或二维数组
dirs = [(-1,0), (1,0), (0,-1), (0,1)]
def dfs(x, y, grid, n, m):
# 边界判断 + 已访问 + 不可通行
if x < 0 or x >= n or y < 0 or y >= m or (x,y) in visited or grid[x][y] != 0:
return
# 标记访问
visited.add((x, y))
# 遍历四个方向
for dx, dy in dirs:
dfs(x+dx, y+dy, grid, n, m)
输入描述
输入描述
输出描述
python
import os
import sys
import copy
# 设置递归深度(防止 DFS 层数过多爆栈)
sys.setrecursionlimit(1500000)
# 输入棋盘大小 n×n
n=int(input())
# vis:访问标记数组
# vis[i][j] = 1 表示该格子已经走过(路径不能重复走)
vis=[[0]*n for _ in range(n)]
# lie:每一列还需要走多少个格子
lie=list(map(int,input().split()))
# hang:每一行还需要走多少个格子
hang=list(map(int,input().split()))
# 目标步数(总路径长度)
# 因为每走一个格子,会同时消耗 行+列 各1
# 所以总步数 = (行总和 + 列总和) / 2
tar=(sum(hang)+sum(lie))//2
# 四个方向(右、下、上、左)
dirs=[[0,1],[1,0],[-1,0],[0,-1]]
# 用来记录最终路径(字符串形式)
p=""
# DFS函数:
# x,y:当前位置
# path:路径(用字符串记录)
# bu:当前已经走的步数
def dfs(x,y,path,bu):
global p
# 标记当前格子已访问
vis[x][y]=1
# 当前行、列需求减1(表示走了这个点)
hang[x]-=1
lie[y]-=1
# ===== 剪枝1:行约束 =====
# 如果当前行已经满足(变成0)
# 那么前面的行必须也已经满足,否则不合法
if hang[x]==0:
for i in range(x):
if hang[i]>0:
return # 不满足,直接剪枝
# ===== 剪枝2:列约束 =====
if lie[y]==0:
for i in range(y):
if lie[i]>0:
return # 不满足,剪枝
# ===== 终点判断 =====
# 如果走到了右下角
if x==n-1 and y==n-1:
# 判断是否满足:
# 1. 所有行列刚好用完
# 2. 步数等于目标步数
if sum(hang)==0 and sum(lie)==0 and bu==tar:
p=path # 记录路径
return # 找到答案,结束
else:
return # 虽然到终点,但不合法
# ===== 枚举四个方向 =====
for xq,yq in dirs:
xi,yi=x+xq,y+yq
# 条件:
# 1. 不越界
# 2. 没访问过
# 3. 该行还有剩余需求
# 4. 该列还有剩余需求
if 0<=xi<n and 0<=yi<n and vis[xi][yi]!=1 and hang[xi]>0 and lie[yi]>0:
# 递归搜索
dfs(xi,yi,path+"/"+str(xi*n+yi),bu+1)
# ===== 回溯(非常关键)=====
vis[xi][yi]=0 # 恢复未访问
hang[xi]+=1 # 恢复行需求
lie[yi]+=1 # 恢复列需求
# 从起点 (0,0) 开始
# 初始路径为 "0"
# 初始步数为 1(已经走了起点)
dfs(0,0,"0",1)
# 输出路径(按题目要求格式)
for i in p.split("/"):
print(i,end=" ")







