DFS
DFS连通性模型
ACwing.1112. 迷宫
https://www.acwing.com/problem/content/1114/
import sys
sys.setrecursionlimit(50020)
xdirs = [0,0,-1,1]
ydirs = [1,-1,0,0]
def dfs(x,y):
if x==xb and y == yb:
return True
for i in range(4):
x1,y1 = x+xdirs[i],y+ydirs[i]
if x1<0 or x1>=n or y1<0 or y1>=n or maze[x1][y1]=='#':
continue
maze[x1][y1] = '#'
if dfs(x1,y1):
return True
# maze[x1][y1] = '.'
return False
T =int(input())
lis = []
for i in range(T):
n = int(input())
maze = []
for i in range(n):
maze.append(list(input()))
xa,ya,xb,yb = map(int,input().split())
if maze[xa][ya]=='#' or maze[xb][yb]=='#':
lis.append('NO')
else:
maze[xa][ya] = '#'
if dfs(xa,ya):
lis.append('YES')
else:
lis.append('NO')
print(*lis,sep='\n')
第二种写法
import sys
sys.setrecursionlimit(50020)
xdirs = [0,0,-1,1]
ydirs = [1,-1,0,0]
def dfs(x,y):
if x==xb and y == yb:
return True
if maze[x][y]=='#':
return False
# 与上面代码不同,但是要多进一个递归层
maze[x][y] = '#'
for i in range(4):
x1,y1 = x+xdirs[i],y+ydirs[i]
if x1<0 or x1>=n or y1<0 or y1>=n or maze[x1][y1]=='#':
continue
if dfs(x1,y1):
return True
# maze[x1][y1] = '.'
return False
T =int(input())
lis = []
for i in range(T):
n = int(input())
maze = []
for i in range(n):
maze.append(list(input()))
xa,ya,xb,yb = map(int,input().split())
if maze[xa][ya]=='#' or maze[xb][yb]=='#':
lis.append('NO')
else:
if dfs(xa,ya):
lis.append('YES')
else:
lis.append('NO')
print(*lis,sep='\n')
AcWing.1113.红与黑
https://www.acwing.com/problem/content/1115/
import sys
xdirs = [0,0,-1,1]
ydirs = [1,-1,0,0]
def dfs(x,y):
global cnt
for i in range(4):
x1,y1 = x+xdirs[i],y+ydirs[i]
if x1<0 or x1>=h or y1<0 or y1>=w or maze[x1][y1]!='.':
continue
maze[x1][y1] = '#'
cnt += 1
dfs(x1,y1)
while True:
w,h = map(int,input().split())
if w==0 and h==0:
break
maze = []
for i in range(h):
maze.append(list(input()))
for i in range(h):
for j in range(w):
if maze[i][j]=='@':
x,y = i,j
cnt = 1
dfs(x,y)
print(cnt)
DFS搜索顺序
AcWing.1116. 马走日
https://www.acwing.com/problem/content/1118/
xdirs = [1,1,-1,-1,2,2,-2,-2]
ydirs = [2,-2,2,-2,1,-1,1,-1]
def dfs(x,y,cnt):
global res
if cnt == n*m:
res += 1
maze[x][y] = True
for i in range(8):
x1,y1 = x+xdirs[i],y+ydirs[i]
if x1<0 or x1>=n or y1<0 or y1>=m or maze[x1][y1]:
continue
dfs(x1,y1,cnt+1)
# 回溯
maze[x][y] = False
T = int(input())
for _ in range(T):
n,m,x,y = map(int,input().split())
maze = [[False]*m for i in range(n)]
res = 0
dfs(x,y,1)
print(res)
AcWing 1117. 单词接龙
https://www.acwing.com/problem/content/1119/
def dfs(s):
global res_max
for new_s in st:
if dic[new_s]>0:
for i in range(len(new_s)-1):
if s.endswith(new_s[:i+1]):
flag = False
dic[new_s]-=1
dfs(s+new_s[i+1:])
dic[new_s]+=1
res_max = max(res_max,len(s))
n = int(input())
st = []
for i in range(n):
st.append(input())
c = input()
dic = {s:2 for s in st}
res_max = 0
for s in st:
if s[0]==c and len(s)>1:
dic[s]-=1
dfs(s)
dic[s]+=1
print(res_max)
AcWing 1118. 分成互质组
https://www.acwing.com/problem/content/1120/
import math
def dfs(cur_len,idx):
global min_res
# 剪枝:如果比当前最短的结果长,则返回
if cur_len>=min_res:
return
if idx == n:
min_res = cur_len
return
i = idx
# 判断和每组是否有满足条件的
# 加进去和不加进去两种方案
for j in range(len(res)):
for num in res[j]:
if math.gcd(lis[i],num)!=1:
break
else:
res[j].append(lis[i])
dfs(cur_len,i+1)
res[j].pop()
res.append([lis[i]])
dfs(cur_len+1,i+1)
res.pop()
n = int(input())
lis = list(map(int,input().split()))
res = []
min_res = 10
dfs(0,0)
print(min_res)
DFS剪枝与优化
AcWing 165. 小猫爬山
https://www.acwing.com/problem/content/167/
def dfs(idx,cur_len):
global min_res
if cur_len>=min_res:
return
if idx==n:
min_res = cur_len
return
for i in range(len(res)):
if lis[idx]+res[i]<=w:
res[i]+=lis[idx]
dfs(idx+1,cur_len)
res[i]-=lis[idx]
res.append(lis[idx])
dfs(idx+1,cur_len+1)
res.pop()
n,w = map(int,input().split())
lis = []
for i in range(n):
lis.append(int(input()))
lis.sort(reverse=True)
res = []
min_res = float('inf')
dfs(0,0)
print(min_res)
AcWing 166. 数独
https://www.acwing.com/problem/content/168/
# 状态压缩+lowbit剪枝
import sys
lowbit = lambda x: x & -x
def change(i, j, num, is_set=True):
if is_set:
lis[i][j] = str(num)
else:
lis[i][j] = '.'
value = 1 << (num - 1)
if not is_set:
value = -value
row[i] -= value
col[j] -= value
maze[i // 3][j // 3] -= value
def get(x,y):
return row[x] & col[y] & maze[x // 3][y // 3]
# 随机搜当前点能搜的数字最少的点
def dfs(q):
# print(q)
if q == cnt:
return True
# x, y = 0,0
min_num = 10
for i in range(9):
for j in range(9):p p
if lis[i][j] == '.':
# 统计能搜的数目
# try:
k = get(i,j)
if min_num > ones[k]:
min_num = ones[k]
x,y = i,j
# except:
# print(k)
# 回溯
k = get(x,y)
while k:
t = map[lowbit(k)]
change(x, y, t)
if dfs(q + 1):
return True
change(x, y, t, False)
k -= lowbit(k)
return False
ones = [0 for i in range(1 << 9)]
for i in range(0, 1 << 9):
for j in range(9):
ones[i] += i >> j & 1
map = [0 for i in range(1 << 9)]
for i in range(9):
map[1 << i] = i + 1
for ipt in sys.stdin:
# ipt = list(input())
if ipt[0] == 'e':
break
lis = [list(ipt[i * 9:(i + 1) * 9]) for i in range(9)]
# print(lis)
row = [(1<<9)-1 for i in range(9)]
col = [(1<<9)-1 for i in range(9)]
maze = [[(1<<9)-1] * 3 for i in range(3)]
cnt = 0
for i in range(9):
for j in range(9):
if lis[i][j] != '.':
change(i, j, int(lis[i][j]))
else:
cnt += 1
dfs(0)
for i in range(9):
print(''.join(lis[i]),end='')
print()
习题
1.发现环
https://www.lanqiao.cn/problems/108/learning/?page=1&first_category_id=1&name=%E5%8F%91%E7%8E%B0%E7%8E%AF
dfs+并查集+拓扑
import os
import sys
# 请在此输入您的代码
def find(u):
if father[u]!=u:
father[u] = find(father[u])
return father[u]
def dfs(u,v):
if u == v:
res.append(v)
visited[v] = 1
res.sort()
print(*res)
return
visited[u] = 1
res.append(u)
for i in G[u]:
if not visited[i]:
dfs(i,v)
res.pop()
n = int(input())
father = [i for i in range(n+1)]
# root = float('inf')
G = [[] for i in range(n+1)]
for i in range(n):
u,v = map(int,input().split())
G[u].append(v)
G[v].append(u)
ui,vi = find(u),find(v)
if ui!=vi:
father[ui] = vi
else:
start,end = u,v
res = []
visited = [0 for i in range(n+1)]
dfs(start,end)
拓扑
from collections import deque
n = int(input())
G = [[] for i in range(n+1)]
insever = [0 for i in range(n+1)]
for i in range(n):
u,v = map(int,input().split())
G[u].append(v)
G[v].append(u)
insever[u]+=1
insever[v]+=1
dq = deque()
for i in range(1,n+1):
if insever[i]==1:
dq.append(i)
st = set()
while dq:
x = dq.popleft()
st.add(x)
for i in G[x]:
insever[i]-=1
if insever[i]==1:
dq.append(i)
res = set(range(1,n+1))-st
lis = list(res)
lis.sort()
print(*lis)