蓝桥杯算法—-搜索

在 Python 中,通常情况下 (x-1), (y-1) 这种写法是用来表示坐标或索引的偏移量,其中 (x, y) 是一个二维空间中的点或位置。
(x-1) 表示在 x 轴上向左移动一个单位;
(y-1) 表示在 y 轴上向上移动一个单位。
这种写法通常用于处理数组、列表、矩阵等数据结构的索引或坐标,特别是在二维数组或矩阵中,因为索引通常是从 0 开始的。例如,如果要访问二维数组的第 (x, y) 个元素,可以使用 (x-1), (y-1) 来表示该元素在数组中的索引位置。
请注意,这种写法假设坐标或索引是从 1 开始计数的,因此需要将其减去 1 以适应 Python 中从 0 开始计数的索引方式。

DFS–基础

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

例题分析

分糖果

在这里插入图片描述

# ans表示方案数
ans = 0
# 1 usage
def dfs(depth, n, m):
    # depth:第几个小朋友
    # n:第一种糖果剩余余量
    # m:第二种糖果剩余余量
 
    # 当分完所有小朋友后保证手上没有糖果
    if depth == 7:  # 如果已经分完所有小朋友
        if n == 0 and m == 0:  # 如果第一种和第二种糖果剩余余量均为0
            global ans
            ans += 1  # 方案数加1
        return
 
    # 枚举当前小朋友的糖果可能性
    # 枚举第一种糖果
    for i in range(0, 6):  # 第一种糖果的数量范围为0到5
        # 枚举第二种糖果
        for j in range(0, 6):  # 第二种糖果的数量范围为0到5
            # 第depth个小朋友有i个第一种糖果,j个第二种糖果
            if 2 <= i+j <= 5 and i <= n and j <= m:  # 如果第一种和第二种糖果总数在2到5之间,并且数量不超过剩余余量
                dfs(depth+1, n-i, m-j)  # 继续递归搜索下一个小朋友
 
dfs(0, 9, 16)  # 从第0个小朋友开始搜索,第一种糖果剩余余量为9,第二种糖果剩余余量为16
print(ans)  # 输出方案数

3505 西瓜

在这里插入图片描述

def dfs(depth, weight, cnt):
    # depth:第depth个瓜
    # weight:表示当前买到的瓜的重量
    # cnt:表示当前批的次数
    
    # 剪枝.当前已经不合法,没必要继续下去
    if weight > m:  # 如果当前买到的瓜的重量超过了目标重量m,则剪枝
        return
    if weight == m:  # 如果当前买到的瓜的重量等于目标重量m
        global ans
        ans = min(ans, cnt)  # 更新答案为当前批次数cnt与答案ans的较小值
    if depth == n:  # 如果已经遍历完所有瓜
        return
 
    # 枚举当前瓜的三种情况
    # 不买
    dfs(depth+1, weight+0, cnt)
    # 买
    dfs(depth+1, weight+A[depth], cnt)
    # 买一半
    dfs(depth+1, weight+A[depth] // 2, cnt+1)
 
# 输入
n, m = map(int, input().split())  # 输入瓜的数量n和目标重量m
m *= 2  # 将目标重量m乘以2,因为每个瓜的重量需要*2处理
A = list(map(int, input().split()))  # 输入每个瓜的重量列表A
A = [x*2 for x in A]  # 将每个瓜的重量乘以2,因为每个瓜的重量需要*2处理
ans = n + 1  # 初始化答案为瓜的数量n+1
dfs(0, 0, 0)  # 调用dfs函数,开始深度优先搜索
if ans == n + 1:  # 如果答案仍然为初始值n+1,表示没有找到符合条件的解
    ans = -1  # 将答案设为-1
print(ans)  # 输出答案

DFS–回溯

回溯法

def dfs(depth):
    # depth:第depth个数字
    if depth == n:  # 如果已经选择完所有数字
        print(path)  # 打印当前路径
        return
 
    # 第depth个数字可以从1-n进行选择
    for i in range(1, n+1):  # 遍历数字1到n
        # 选择的数字必须未被标记
        if vis[i]:  # 如果数字i已经被选择过
            continue  # 跳过选择
 
        # 第depth个数字选择i
        vis[i] = True  # 标记数字i已经被选择
        path.append(i)  # 将数字i添加到路径中
        dfs(depth + 1)  # 继续选择下一个数字
        vis[i] = False  # 恢复数字i的未选择状态
        path.pop(-1)  # 移除数字i,回溯到上一层
 
n = int(input())  # 输入数字n
vis = [False] * (n + 1)  # 初始化数字标记列表
path = []  # 初始化路径列表
dfs(0)  # 从第0个数字开始选择

求子集

n = int(input())  # 输入n
a = list(map(int, input().split()))  # 输入a列表
 
path = []  # 定义路径数组
 
def dfs(depth):
    # 当深度等于n时,打印路径并返回
    if depth == n:
        print(path)
        return
    
    # 选取当前深度对应的元素
    path.append(a[depth])
    dfs(depth + 1)  # 递归下一层
    
    path.pop(-1)  # 不选取当前深度对应的元素
    dfs(depth + 1)  # 递归下一层
 
dfs(0)  # 从第0层开始深度优先搜索

N 皇后

在这里插入图片描述

def dfs(x):
    # 定义深度优先搜索函数,x 表示当前层级
    if x == n + 1:
        # 如果已经放置了 n 个皇后,即所有行都已经遍历完成
        global ans
        ans += 1  # 结果加一
        return  # 返回
 
    # 遍历当前层级的每一列
    for y in range(n):
        # 当前坐标为 (x, y),需要满足当前列、主对角线、副对角线上没有皇后
        if vis1[y] or vis2[x + y] or vis3[x - y + n]:
            # 如果当前列已经有皇后,或者主副对角线上已经有皇后,跳过当前位置
            continue
 
        # 在当前位置放置皇后,标记当前列、主对角线、副对角线上有皇后
        vis1[y] = vis2[x + y] = vis3[x - y + n] = True
        # 递归调用下一层,即放置下一个皇后
        dfs(x + 1)
        # 回溯,撤销当前位置的皇后,继续尝试其他位置
        vis1[y] = vis2[x + y] = vis3[x - y + n] = False
 
# 获取输入的皇后数量
n = int(input())
# 初始化三个标记数组,用于标记列、主对角线、副对角线是否已经有皇后
vis1 = [False] * (n + 1)
vis2 = [False] * (2 * n + 1)
vis3 = [False] * (2 * n + 1)
# 初始化结果变量
ans = 0
# 调用深度优先搜索函数,从第一行开始放置皇后
dfs(1)
# 输出结果
print(ans)

小朋友崇拜圈

在这里插入图片描述

在这里插入图片描述

# 定义深度优先搜索函数,用于找出环并计算环的长度
def dfs(x, length):
    # 记录走到 x 的步长为 length
    vis[x] = length
 
    # 接下来要走下一个点
    # 判断下一个点是否走过
    if vis[a[x]] != 0:
        # 此时存在环
        global ans
        ans = max(ans, length - vis[a[x]] + 1)
        pass
    else:
        dfs(a[x], length + 1)
 
# 输入点的个数
n = int(input())
# 输入每个点的下一个点的索引,注意索引从1开始,所以在前面添加了一个0
a = [0] + list(map(int, input().split()))
# 标记数组: vis[x] 表示点 x 的步数
vis = [0] * (n + 1)
# 初始化结果变量
ans = 0
# 遍历每个点,对于每个单独的环,都要做一遍深度优先搜索
for i in range(1, n + 1):
    if vis[i] == 0:
        dfs(i, 1)
# 输出结果
print(ans)

def dfs(x, length)::定义了一个深度优先搜索函数 dfs,其中 x 表示当前遍历到的点的索引,length 表示当前路径的长度。
vis[x] = length:将当前点的步数记录为 length。
if vis[a[x]] != 0::判断当前点的下一个点是否已经被访问过。
global ans:声明 ans 为全局变量。
ans = max(ans, length - vis[a[x]] + 1):更新结果变量 ans,取当前路径长度与之前记录的路径长度的差的最大值。
else: dfs(a[x], length + 1):如果当前点的下一个点未被访问过,则继续深度优先搜索。
n = int(input()):输入点的个数。
a = [0] + list(map(int, input().split())):输入每个点的下一个点的索引,将索引保存在列表 a 中。
vis = [0] * (n + 1):初始化标记数组 vis,用于记录每个点的步数。
ans = 0:初始化结果变量 ans。
for i in range(1, n + 1)::遍历每个点。
if vis[i] == 0::如果当前点未被访问过,则进行深度优先搜索。
dfs(i, 1):调用深度优先搜索函数 dfs,从当前点开始搜索环。
print(ans):输出结果变量 ans,即找到的最长环的长度。

全球变暖

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值