DFS-深度有限搜索-Python

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)
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值