笔记:蓝桥杯python搜索(3-2)——DFS剪支和记忆化搜索
目录
一、DFS剪支
二、例题
P2942 数字王国之军训军队
P3075 特殊的多边形
三、记忆化搜索
四、例题
例题 P3820 混境之地
P216 地宫取宝
一、DFS剪支
- 在搜索过程中,如果需要完全遍历所有情况可能需要很多时间
- 在搜索到某种状态时,根据当前状态判断出后续无解,则该状态无需继续深入搜索
- 例如:给定N个正整数,求出有多少个子集之和小于等于K。在搜索过程中当前选择的数字和已经超过K则不需要继续搜索。
- 可行性剪枝:当前状态和题意不符,并且往后的所有情况和题意都不符,那么就可以进行剪枝。
- 最优性剪枝:在搜索过程中,当前状态已经不如已经找到的最优解,也可以剪枝,不需要继续搜索。
二、例题
P2942 数字王国之军训军队
数字王国开学了,它们也和我们人类一样有开学前的军训,现在一共有 n 名学生,每个学生有自己的一个名字 ai(数字王国里的名字就是一个正整数,注意学生们可能出现重名的情况),此时叛逆教官来看了之后感觉十分别扭,决定将学生重新分队。
排队规则为:将学生分成若干队,每队里面至少一个学生,且每队里面学生的名字不能出现倍数关系(注意名字相同也算是倍数关系)。
现在请你帮忙算算最少可以分成几队?
例:有 4 名学生 (2,3,4,4),最少可以分成 (2,3)、(4)、(4) 共 3 队。
输入格式
第一行包含一个正整数 n,表示学生数量。
第二行包含 n 个由空格隔开的整数,第 i 个整数表示第 i 个学生的名字 ai。
输出格式
输出共 1 行,包含一个整数,表示最少可以分成几队。
DFS 搜索,枚举每个学生分到每个组内
可行性剪枝:要满足题目条件
最优性剪枝:判断当前状态是否比 ans 更劣
def check(x,group):for y in group:if x%y ==0 or y%x==0:return Falsereturn Truedef dfs(depth):if depth==n:global answeranswer=min(answer,len(Groups))returnfor every_group in Groups:if check(a[depth],every_group):every_group.append(a[depth])dfs(depth+1)every_group.pop()Groups.append([a[depth]])dfs(depth+1)Groups.pop()n=int(input())
a=list(map(int,input().split()))
Groups=[]
answer=n
dfs(0)
print(answer)
# 判断x能否加入group组
def check(x, group):# 要保证不能存在倍数关系for y in group:if x % y == 0 or y % x == 0:return Falsereturn True# depth表示当前为第depth个学生
def dfs(depth):global ans# 最优性剪枝:当前已经比ans大,说明该策略不可行if len(Groups) > ans:returnif depth == n:ans = min(len(Groups), ans)returnfor each_group in Groups:# 枚举第depth个学生能否加入当前组each_group# 剪枝:必须满足题意if check(a[depth], each_group):each_group.append(a[depth])dfs(depth + 1)each_group.pop()# 单独作为一组,将 a[depth] 作为一个新的分组添加,即 Groups.append([a[depth]])Groups.append([a[depth]])dfs(depth + 1)Groups.pop()n = int(input())
a = list(map(int, input().split()))
# ans表示最少能分多少队
ans = n# Groups表示分组情况
Groups = []
dfs(0)
print(ans)
P3075 特殊的多边形
假设一个 n 边形 n 条边为 a1,a2,a3,⋯,an,定义该 n 边形的值 v=a1×a2×a3×⋯×an。
定义两个 n 边形不同是指至少有一条边的长度在一个 n 边形中有使用而另一个 n 边形没有用到,如 n 边形 (3,4,5,6)和 (3,5,4,6) 是两个相同的 n 边形,(3,4,5,6)和 (4,5,6,7) 是两个不相同的 n 边形。
现在有 t 和 n,表示 t 个询问并且询问的是 n 边形,每个询问给定一个区间 [l,r],问有多少个 n 边形(要求该 n 边形自己的 n 条边的长度互不相同)的值在该区间范围内。
输入格式
第一行包含两个正整数 t、n,表示有 t 个询问,询问的是 n 边形。
接下来 t 行,每行有两个空格隔开的正整数 l、r,表示询问区间 [l,r]。
输出格式
输出共 t 行,第 i行对应第 i 个查询的 n 边形个数。
-
先考虑简单版:乘积为 v 有多少种 n 边形
-
DFS 处理出所有乘积对应的所有可能
-
维护一个递增的边长序列(唯一性)
-
枚举第 i 边的长度,最小最大范围(剪枝)
-
最终 check 是否满足 N 边形:
-
最小的 N - 1 条边之和大于第 N 边
-
-
-
预处理+前缀和 O(1)查询答案
import os
import sys# 请在此输入您的代码
def dfs(depth, last_val, tot, mul):""":param depth: 第depth条边长:param last_val: 上一边长长度:param tot: 累计和:param mul: 累计乘积"""if depth == n:# 前n-1条边之和大于第n条边if tot - path[-1] > path[-1]:ans[mul] += 1returnfor i in range(last_val + 1, 100001):# 最优性剪枝, 后续还有n-depth个数字, 每个数字都要>=i# 累计乘积要不超过100000: mul * (i ** (n - depth))if mul * (i ** (n - depth)) > 100000:breakpath.append(i)dfs(depth + 1, i, tot + i, mul * i)path.pop()t, n = map(int, input().split())
ans = [0] * 100001
path = []
dfs(0, 0, 0, 1)for i in range(1, 100001):ans[i] += ans[i - 1]
for _ in range(t):l, r = map(int, input().split())print(ans[r] - ans[l - 1])
三、记忆化搜索
- 记忆化:通过记录已经遍历过的状态的信息,从而避免对同一状态重复遍历的搜索实现方式。
- 记忆化=dfs+额外字典
- 如果先前已经搜索过:直接查字典,返回字典中结果
- 如果先前没有搜索过:继续搜索,最终将该状态结果记录到字典中
- 斐波那契数列:设F[0] = 1, F[1] = 1, F[n] = F[n - 1] + F[n - 2],求F[n],结果对1e9 + 7取模。 0 <= n <= 10000
- 样例输入: 5000
- 样例输出: 976496506
def f(n):if n==0 or n==1:return 1return (f(n-1)+f(n-2))%(1e9+7)
n=int(input())
print(f(n))
# 直接递归存在大量重复计算
计算 F(5) 时,要先算 F(4) 和 F(3);算 F(4) 又需算 F(3) 和 F(2),这里 F(3) 就被重复计算了。随着 n 增大,像 F(2)、F(3) 这类中间结果会被反复多次计算,导致时间复杂度呈指数级增长,效率极低。
- 每次搜索时将当前状态答案记录到字典中
- 后续搜索直接返回结果
import sys
sys.setrecursionlimit(100000)# 记忆化1
dic={0:1,1:1}
def f(n):if n in dic.keys():return dic[n]dic[n]=(f(n-1)+f(n-2))%1000000007return dic[n]
n=int(input())
print(f(n))
from functools import lru_cache#记忆化搜索2 @lru_cache(maxsize=None)
from functools import lru_cache# 记忆化2
@lru_cache(maxsize=None)
def f(n):if n==0 or n==1:return 1return f(n-1)+f(n-2)
n=int(input())
print(f(n))
四、例题
例题 P3820 混境之地
小蓝有一天误入了一个混境之地。
好消息是:他误打误撞拿到了一张地图,并从中获取到以下信息:
混境之地是一个 n⋅m 大小的矩阵,其中第 i 行第 j 列的的点 hij 表示第 i 行第 j 列的高度。
他现在所在位置的坐标为 (A,B) ,而这个混境之地出口的坐标为 (C,D) ,当站在出口时即表示可以逃离混境之地。
小蓝有一个喷气背包,使用时,可以原地升高 k 个单位高度。
坏消息是:
由于小蓝的体力透支,所以只可以往低于当前高度的方向走。
喷漆背包燃料不足,只可以最后使用一次。
小蓝可以往上下左右四个方向行走,不消耗能量。
小蓝想知道他能否逃离这个混境之地,如果可以逃离这里,输入
Yes,反之输出No。
输入格式
第 1 行输入三个正整数 n,m 和 k , n,m 表示混境之地的大小, k 表示使用一次喷气背包可以升高的高度。
第 2 行输入四个正整数 A,B,C,D ,表示小蓝当前所在位置的坐标,以及混境之地出口的坐标。
第 3 行至第 n+2 行,每行 m 个整数,表示混境之地不同位置的高度。
输出格式
输出数据共一行一个字符串:
若小蓝可以逃离混境之地,则输出
Yes。若小蓝无法逃离混境之地,则输出
No。
走到(x,y),z表示是否使用喷气背包
当x,y,z固定时,具有唯一解,因此可以使用记忆化搜索
时间复杂度<x,y,z>三元组数量:1000*1000*2
from functools import lru_cache#记忆化搜索2
@lru_cache(maxsize=None)
def dfs(x, y, z):# print(x, y, z)# 当前处于(x,y), z表示是否使用喷气背包# 如果能逃离, 返回True, 否则返回Falseif x == C - 1 and y == D - 1:return True#没走到终点,四个方向判断for i in range(4):xx, yy = x + dir[i][0], y + dir[i][1]#不能越界if xx < 0 or xx >= n or yy < 0 or yy >= m:continue#新坐标比旧坐标低,走到新坐标(xx,yy)if Map[xx][yy] < Map[x][y]:if dfs(xx, yy, z):return True#在(x,y)处使用喷气背包elif Map[xx][yy] < Map[x][y] + k and z == False:if dfs(xx, yy, True):return Truereturn False# 四个方向
dir = [(1, 0), (0, 1), (-1, 0), (0, -1)]
n, m, k = map(int, input().split())
A, B, C, D = map(int, input().split())
Map = []
for i in range(n):Map.append(list(map(int, input().split())))
if dfs(A - 1, B - 1, False):print("Yes")
else:print("No")
P216 地宫取宝
X 国王有一个地宫宝库。是 n×m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。
地宫的入口在左上角,出口在右下角。
小明被带到地宫的入口,国王要求他只能向右或向下行走。
走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。
当小明走到出口时,如果他手中的宝贝恰好是 k 件,则这些宝贝就可以送给小明。
请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这 k 件宝贝。
输入描述
输入一行 3 个整数,用空格分开:n,m,k (1≤n,m≤50,1≤k≤12)。
接下来有 n 行数据,每行有m 个整数 Ci (0≤Ci≤12) 代表这个格子上的宝物的价值。
输出描述
要求输出一个整数,表示正好取 k 个宝贝的行动方案数。该数字可能很大,输出它对 10^9+7 取模的结果。
从(x,y)出发,先前已经有宝物z件,已有的最大宝物价值为w的方案数记为dfs(x,y,z,w)
只要确定四元组,就确定当前的方案数
答案=dfs(1,1,0,-1)
最终点=dfs(n,m,z,?) or dfs(n,m,z - 1,?)
(x,y)处可选,可不选,然后可以往右走或者往下走
from functools import lru_cache@lru_cache(maxsize=None)
def dfs(x, y, z, w):#从(x,y)出发,先前已有z件宝物,已有宝物最大价值为w#走到终点if x == n and y == m:#当前不需要选择if z == k:return 1#当前需要选择if z == k - 1:if w < a[x][y]:return 1#其他情况,均为0return 0ans = 0#遍历两个方向for delta_x, delta_y in [(1, 0), (0, 1)]:xx, yy = x + delta_x, y + delta_yif xx <= n and yy <= m:# 当前不选择ans += dfs(xx, yy, z, w)# 当前选择if w < a[x][y]:ans += dfs(xx, yy, z + 1, a[x][y])return ans % 1000000007n, m, k = map(int, input().split())
a = [[0]*(m+1)]
for i in range(n):a.append([0] + list(map(int, input().split())))
print(dfs(1, 1, 0, -1))
相关文章:
笔记:蓝桥杯python搜索(3-2)——DFS剪支和记忆化搜索
目录 一、DFS剪支 二、例题 P2942 数字王国之军训军队 P3075 特殊的多边形 三、记忆化搜索 四、例题 例题 P3820 混境之地 P216 地宫取宝 一、DFS剪支 在搜索过程中,如果需要完全遍历所有情况可能需要很多时间在搜索到某种状态时,根据当前状态判断…...
ChatBox+硅基流动Deepseek_R1开源API 满血(671B)部署教程,全程干货无废话
DeepSeek开源深度推理模型火爆发布,网络流量过大经常导致服务器崩溃,所以一般有两种方法解决这个问题 如果你的硬件支持,或者保密文档,保密单位,那么可以部署在本地端。但是再好的电脑也不能让DS满血复活,…...
35~37.ppt
目录 35.张秘书-《会计行业中长期人才发展规划》 题目 解析 36.颐和园公园(25张PPT) 题目 解析 37.颐和园公园(22张PPT) 题目 解析 35.张秘书-《会计行业中长期人才发展规划》 题目 解析 插入自定义的幻灯片:新建幻灯片→重用…...
畅快使用DeepSeek-R1的方法
腾讯云API接入Cherry Studio简明指南-畅快使用DeepSeek-R1 注意:腾讯云API针对deepseek限时免费(后续即使收费也较为便宜,可以作为长期使用的方法),并且比华为的API要快不少。 一、获取腾讯云API密钥 登录并进入腾讯…...
【人工智能】Python中的序列到序列(Seq2Seq)模型:实现机器翻译
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 序列到序列(Seq2Seq)模型是自然语言处理(NLP)中一项核心技术,广泛应用于机器翻译、语音识别、文本摘要等任务。本文深入探讨Seq2Seq模…...
【算法】动态规划专题⑥ —— 完全背包问题 python
目录 前置知识进入正题模板 前置知识 【算法】动态规划专题⑤ —— 0-1背包问题 滚动数组优化 完全背包问题是动态规划中的一种经典问题,它与0-1背包问题相似,但有一个关键的区别:在完全背包问题中,每种物品都有无限的数量可用。…...
记一次基于manifest v3开发谷歌插件
背景 头疼在国际化功能普遍的前端项目中,如果你在处理或者在某一块功能上新增一些需求的时候,在没有国际化功能的页面中,我们随便复制一些文本,然后在vs code中全局搜索,很快就可以找到所要更改的代码文件在哪里&…...
C# OpenCvSharp 部署MOWA:多合一图像扭曲模型
目录 说明 效果 项目 代码 下载 参考 C# OpenCvSharp 部署MOWA:多合一图像扭曲模型 说明 算法模型的paper名称是《MOWA: Multiple-in-One Image Warping Model》 ariv链接 https://arxiv.org/pdf/2404.10716 效果 Stitched Image 翻译成中文意思是&…...
本地部署DeepSeek-R1模型(新手保姆教程)
背景 最近deepseek太火了,无数的媒体都在报道,很多人争相着想本地部署试验一下。本文就简单教学一下,怎么本地部署。 首先大家要知道,使用deepseek有三种方式: 1.网页端或者是手机app直接使用 2.使用代码调用API …...
神经网络常见激活函数 5-PReLU函数
文章目录 PReLU函数导函数函数和导函数图像优缺点pytorch中的PReLU函数tensorflow 中的PReLU函数 PReLU 参数化修正线性单元:Parametric ReLU 函数导函数 PReLU函数 P R e L U { x x > 0 α x x < 0 ( α 是可训练参数 ) \rm PReLU \left\{ \begin{array}{} x \qua…...
2025我的第二次社招,写在春招之季
先说一个好消息,C那些事 4w star了! 前面断更了一个月,本篇文章就可以看到原因,哈哈。 大家好,我叫光城,腾讯实习转正做后端开发,后去小公司做数据库内核,经过这几年的成长与积累&am…...
Visual Studio Code中文出现黄色框子的解决办法
Visual Studio Code中文出现黄色框子的解决办法 一、vsCode中文出现黄色框子-如图二、解决办法 一、vsCode中文出现黄色框子-如图 二、解决办法 点击 “文件”点击 “首选项”点击 “设置” 搜索框直接搜索unicode选择“文本编辑器”,往下滑动,找到“Un…...
threejs开源代码之-旋转的彩色立方体
效果:旋转的彩色立方体 效果描述: 一个立方体在场景中旋转。立方体的每个面有不同的颜色。使用自定义着色器为立方体添加动态的光影效果。 代码实现 import * as THREE from three; import { OrbitControls } from three/examples/jsm/controls/OrbitC…...
visual studio 2008的试用版评估期已结束的解决办法
visual studio 2008试用期过了后,再次启动时提示:visual studio的试用版评估期已结束。 需要的工具:补丁文件PatchVS2008.exe 解决办法: 1.在“控制面板”-“添加删除程序”中选择visual studio 2008,点击“更改/卸载”…...
解锁 DeepSeek 模型高效部署密码:蓝耘平台深度剖析与实战应用
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
Http和Socks的区别?
HTTP 和 SOCKS 的区别 HTTP 和 SOCKS 都是用于网络通信的协议,但它们在工作原理、应用场景和实现方式上有显著的区别。以下是详细的对比和说明。 一、HTTP 协议 1. 定义 HTTP(HyperText Transfer Protocol)是用于传输超文本数据的应用层协…...
VC播放mp3的方法
1、使用msi库 #include <mmsystem.h> #pragma comment(lib,"winmm.lib") .......//打开文件MCI_OPEN_PARMS mciOpen; mciOpen.lpstrDeviceType _T("mpegvideo"); mciOpen.lpstrElementName _T("c://1.mp3"); MCIERROR mciError mci…...
Docker 部署 verdaccio 搭建 npm 私服
一、镜像获取 # 获取 verdaccio 镜像 docker pull verdaccio/verdaccio 二、修改配置文件 cd /wwwroot/opt/docker/verdaccio/conf vim config.yaml config.yaml 配置文件如下,可以根据自己的需要进行修改 # # This is the default configuration file. It all…...
49-拓展(1)
49-拓展(1) 扩展概述 扩展可以为在当前 package 可见的类型(除函数、元组、接口)添加新功能。 当不能破坏被扩展类型的封装性,但希望添加额外的功能时,可以使用扩展。 可以添加的功能包括: …...
国产编辑器EverEdit - 在文件中查找和替换
1 在文件中查找和替换 1.1 应用场景 某些场景,用户需要在所有工程文件中进行查找和替换关键词,比如:查找工程中哪些文件使用了某个常量。 1.2 使用方法 选择主菜单查找 -> 在文件中查找和替换,或使用快捷键Ctrl Shift F&a…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
