一道题带你领略DFS-记搜-DP

数独(一道经典的dfs题目) 数独 数独是一种传统益智游戏,你需要把一个 9×9 的数独补充完整,使得图中每行、每列、每个 3×3 的九宫格内数字 1∼9 均恰好出现一次。 请编写一个程序填写数独。 输入格式 输入包含多组测试用例。 每个测试用例占一行,包含 81 个字符,代表数独的 81 个格内数据(顺序总体由上到下,同行由左到右)。 每个字符都是一个数字(1−9)或一个 .(表示尚未填充)。 您可以假设输入中的每个谜题都只有一个解决方案。 文件结尾处为包含单词 end 的单行,表示输入结束。 输出格式 每个测试用例,输出一行数据,代 阅读详情

前言

如题所言,DFS-记搜-DP是蓝桥杯比赛中最常用的几种方法,熟练掌握它们,拿奖将易如反掌。下面我们通过2014年地宫取宝问题,来一探这道题的3种不同的想法

题目描述

X 国王有一个地宫宝库。是 n×m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。

地宫的入口在左上角,出口在右下角。

小明被带到地宫的入口,国王要求他只能向右或向下行走。

走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。

当小明走到出口时,如果他手中的宝贝恰好是 k 件,则这些宝贝就可以送给小明。

请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k 件宝贝。

输入描述

输入一行 3 个整数,用空格分开: n , m , k ( 1 ≤ n , m ≤ 50 , 1 ≤ k ≤ 12 ) n,m,k (1≤n,m≤50,1≤k≤12) n,m,k(1≤n,m≤50,1≤k≤12)。

接下来有 n 行数据,每行有 m 个整数 C i   ( 0 ≤ C i ≤ 12 ) C_i\ (0 \leq C_i \leq 12) Ci​ (0≤Ci​≤12)
​ 代表这个格子上的宝物的价值。

输出描述

要求输出一个整数,表示正好取 kk 个宝贝的行动方案数。该数字可能很大,输出它对 1 0 9 + 7 10^9+7 109+7 取模的结果。

输入输出样例

示例

输入

2 2 2
1 2
2 1

输出

2

1. DFS

会超时
dfs下标从左到右依次为
x,y,当前已经取的宝物个数,所取宝物中的最大价值

#include <iostream>
using namespace std;
const int N = 60, MOD = 1e9 + 7;
int n, m, k;
int w[N][N];

int dfs(int x, int y, int u, int v) {
	if (x > n || y > m || u > k) return 0; // 判界
	if (x == n && y == m) { // 到达右下角
		// 已经拿了k个宝物或者加上右下角的最后一个宝物共k个
		if (u == k || u == k - 1 && w[x][y] > v) return 1;
		else return 0; 
	}
	if (w[x][y] > v) { // 当前位置的宝物价值比手里的大
		// 捡或不捡均可
		return dfs(x + 1, y, u, v) + dfs(x, y + 1, u, v)
		+ dfs(x+1, y, u+1, w[x][y]) + dfs(x, y+1, u+1, w[x][y]);
	} else {
		// 只有不捡
		return dfs(x + 1, y, u, v) + dfs(x, y + 1, u, v);
	}
}

int main() {
	cin >> n >> m >> k;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			cin >> w[i][j];
	cout << dfs(1, 1, 0, -1) % MOD << endl;
	
	return 0;
}

2. 记忆化搜索

用一个数组存储过程中的值,避免了重复的计算,极大的减少了时间的使用,可以通过测试点
最明显的一个区别是记忆化搜索最后的答案是存储在第一个数组当中
并且它在过程中就要进行判界

#include <iostream>
#include <cstring>
using namespace std;
const int N = 60, MOD = 1e9 + 7;
int n, m, k;
int w[N][N];
int f[N][N][13][14];

int dfs(int x, int y, int u, int v) {
	if (f[x][y][u][v] != -1) return f[x][y][u][v];
	
	if (x == n && y == m) {
		if (u == k || u == k-1 && w[x][y] > v) return f[x][y][u][v] = 1;
		else return f[x][y][u][v] = 0;
	}
	
	long long s = 0;
	if (x + 1 <= n) {
		if (w[x][y] > v) s+= dfs(x+1, y, u+1, w[x][y]);
		s += dfs(x+1, y, u, v);
	} 
	
	if (y + 1 <= m) {
		if (w[x][y] > v) s+= dfs(x, y+1, u+1, w[x][y]);
		s += dfs(x, y+1, u, v);
	}
	
	return f[x][y][u][v] = s % MOD;
}

int main() {
	cin >> n >> m >> k;
	
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) {
			cin >> w[i][j];
			w[i][j]++;
		}
			
	
	memset(f, -1, sizeof f);
	dfs(1, 1, 0, 0); // 0 = -1
	
	cout << f[1][1][0][0] << endl;
	
	return 0;
}

3. DP

DP则是这道题的最佳解法,如果已经想出前面两种方法,稍加改变就能得到DP。由于我们平常的DP多是一维至二维,所以在到达4维的时候难免会产生怀疑,但还是要坚定地往下做。

  • 状态表示f[i][j][u][v]:表示到达(i,j)位置时,所拿宝物数量为u个,最大价值为v的合法的方案数
  • 状态计算:由于题目限定,只能往右或者往下,所以我们可以根据这个将集合分为两大类。往右时,同时位置上的宝物大于手中的,可以选择取或者不取,为其方案数的加和;若宝物小于手中的最大值,只有不取这种情况。往下同理。
#include <iostream>
using namespace std;
const int N = 60, MOD = 1e9 + 7;
int w[N][N];
int f[N][N][13][14];
int n, m, k;

int main() {
	scanf("%d%d%d", &n, &m, &k);
	
	for (int i = 1; i <= n; i++) 
		for (int j = 1; j <= m; j++) {
			cin >> w[i][j];
			w[i][j]++;
			// 宝贝的价值可以是0, 而-1不能用于索引,因此全部+1
		}
	
	// 初始化1,1位置上的值
	f[1][1][0][0] = 1; // 不取
	f[1][1][1][w[1][1]] = 1; // 取
	
	 
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (i == 1 && j == 1) continue;
			for (int u = 0; u <= k; u++) {
				for (int v = 0; v < 13; v++) {
					int& val = f[i][j][u][v];
					// 不取当前位置,状态由左上方转移而来,加和
					val = (val + f[i-1][j][u][v]) % MOD;  
					val = (val + f[i][j-1][u][v]) % MOD;
					if (u > 0 && w[i][j] == v) {
						for (int c = 0; c < v; c++) {
							val = (val + f[i-1][j][u-1][c]) % MOD;  
							val = (val + f[i][j-1][u-1][c]) % MOD;
						}
					}
				}
			}
		}
	}
	// n,m,k都确定下来,枚举最后结果中所有的最大价值
	int res = 0;
	for (int i = 0; i < 13; i++) res = (res + f[n][m][k][i]) % MOD;
	cout << res << endl; 
	
	return 0;
}

地宫取宝-原题链接

Python编程进阶:从NOJ作业到算法思维与工程实践 在编程学习中,掌握基础语法只是起点,真正的核心在于培养算法思维和解决复杂问题的能力。算法思维是一种将实际问题抽象为计算模型,并通过逻辑与数据结构高效求解的方法论,其价值在于提升代码的效率、可维护性与可扩展性。在工程实践中,这种思维广泛应用于数据处理、系统优化、自动化脚本等场景。本文以Python编程为例,深入探讨如何通过经典题目训练,将字符串处理、数学模拟、基础算法与数据结构应用等知识融会贯通。文中融入了贪心算法和模拟算法等关键概念,旨在帮助学习者从完成作业的层面,跃升至掌握一类问题解法的层面,为后续深入学 阅读详情

相关推荐

Screenshot_2026-11-03-16-23-09-34.jpg

Screenshot_2026-11-03-16-23-09-34.jpg

图的深度遍历

题目描述 请定一个无向图,顶点编号从0到n-1,用深度优先搜索(DFS),遍历并输出。遍历时,先遍历节点编号小的。 输入 输入第一行为整数n(0 < n < 100),表示数据的组数。 对于每组数据,第一行是两个整数k,m(0 < k < 100,0 < m < k*k),表示有m条边,k个顶点。 下面的m行,每行是空格隔开的两个整数u,v,表示一条连接u,v顶点的无向...

691

研发流程后端开发工具,提示功能开发效率

后端开发工具

算法基础dfs

dfs

qq_50438796的博客 312

机器人具有扰动抑制功能的有限时间基于方位角的领航者-跟随者编队控制(Matlab代码实现)

内容概要:本文档标题为《Plecs全桥LLC谐振变换器仿真模型.txt》,但实际内容并未涉及该主题的具体技术细节或仿真建模过程。相反,文档实质是一份由科研服务团队发布的跨学科资源目录,集中展示了大量基于Matlab、Simulink、Python、PSCAD等平台实现的科研项目与算法开发案例,涵盖电力系统、无人机路径规划、微电网优化、状态估计、信号处理、车间调度、图像处理、通信技术、雷达追踪、智能优化算法等多个工程技术领域。每个条目以“【】”标注研究主题,并注明“Matlab代码实现”“Python代码实现”等形式,表明其为可提供技术支持与代码资源的服务项目。文档末尾频繁出现“完整资源下载:公众号——荔枝科研社”及百度网盘链接,明确体现出其作为科研辅助服务推广与引流工具的功能属性。; 适合人群:面向电气工程、自动化、控制科学与工程、计算机科学、智能制造、新能源、航空航天、通信工程及相关交叉学科的研究生、高校教师、科研人员及企业研发工程师。; 使用场景及目标:①为科研人员提供课题选题、技术路线设计与算法实现的参考范例;②辅助学生或研究人员完成课程设计、毕业论文、项目仿真与算法复现任务;③作为第三方技术服务团队的能力展示目录,便于潜在客户快速了解其在多领域提供的定制化仿真与算法开发服务范围。; 阅读建议:此文档并非传统意义上的学术论文或技术教程,而是一份高度碎片化、广告性质浓厚的资源索引清单。读者应忽略其误导性的文件名,将其视为一个综合性科研技术服务目录,重点关注自身研究方向相关的条目,并通过文末提供的公众号或网盘链接进一步获取具体代码与资料。同时,需注意甄别资源的技术质量、原创性与适用性,避免盲目依赖外部服务。

赴美参加学术会议办理流程

有幸能在研究生阶段获得学校资助出国参加学术会议,首先要感谢学校的支持,以及学院和实验室的各位老师~ 接下来说下参会整个准备过程: 本人在接到论文录用通知后,就开始办理相关手续。因为会议地点是美国夏威夷,而且录用通知时间与会议召开时间只隔两个月左右,所以接下来两个月时间要办好学校出国申请手续,赴美签证,因为专业原因,据说签证不好办,所以时间比较紧。学校出国申请和签证相关材料是并行进行的,赴美花费...

xingxin_xu的博客 3195

dfs算法经典例题c语言,算法学习:深度优先搜索(DFS)经典例题(一)

题目描述输入第一行输入一个整数N,表示共有N组测试数据每一组数据都是先输入该地图的行数m(0然后,输入接下来的m行每行输入n个数,表示此处有水还是没水(1表示此处是水池,0表示此处是地面)输出输出该地图中水池的个数。每个水池的旁边(上下左右四个位置)如果还是水池的话的话,它们可以看做是同一个水池。样例输入23 41 0 0 00 0 1 11 1 1 05 51 1 1 1 00 0 1 0 10...

weixin_34790081的博客 978

VBA学习笔记6:将多个工作表中满足条件的数据汇总到同一个工作表

VBA学习笔记6:将多个工作表中满足条件的数据汇总到同一个工作表

weixin_45355881的博客 4708

hdu3555,hdu2089 数位dp

第一次做数位dp,最开始的2089题我是用

Merc_A的专栏 558

树莓派安装snowboy

1、树莓派换源 参考链接:https://blog.youkuaiyun.com/qq_43556844/article/details/113615915 2、更新pip3 参考链接:https://blog.youkuaiyun.com/qq_43556844/article/details/113616214 3、存取麦克风 我们使用PortAudio作为音频输入/输出的跨平台支持。我们还使用sox作为快速实用程序来检查麦克风设置是否正确。 sudo apt-get install python-pyaudio python

qq_43556844的博客 1923

【AI Agent】Hermes Agent解析

Hermes Agent:一个具备持久化学习能力的开源AI Agent框架 核心特点: 突破传统Agent的"无状态困境",通过记忆系统(SQLite+FTS5全文检索)实现跨会话经验积累 支持200+模型自由切换,11种模型家族和15+平台接入 五层架构设计(入口层、编排层、推理层、工具执行层、存储层)实现平台无关性 47+内置工具和动态技能沉淀机制,支持从任务执行中自动提炼可复用Skill 独特的四层记忆体系(会话/每日/长期/向量索引)和辩证式用户建模 与传统Agent对比: 具备自我进化能力,通过A

sysu_lluozh 948

【hdu】1520 Anniversary party【树形dp】

题意: 一群人种有上下属关系,构成了一棵树,每个人都有一个价值,直接的上下属不能被加入同一个集合,问一个集合最大能有多少价值 题解: 赤裸裸的树形dp,这是我系统的开始学树形dp的第一道题,算是领略了一些树形dp的要点 dp[i][0]记录不取i节点所能得到的在以i节点为根的子树中所能取得的最大价值,dp[i][1]记录取i节点以i节点为跟所能取得的最大价值 遍历i的儿子 dp[i][0

a709743744的博客 331

MicroCap声学仿真介绍(五)-倒相管扬声器系统仿真

实际倒相管的扬声器单体选择、后腔容积、倒相管的直径和长度都是需要精心挑选的,为了便于演示,随意指定了倒相管的长度和直径,现实中还是不能这么随便的。之前介绍了封闭式扬声器的仿真,今天在封闭式扬声器的基础上,再介绍一下倒相管扬声器系统的仿真。

山无忧的博客 1718

本周博客总结

最开始学acm是从dfs入门的,当时看题的时候就看到好多dfs题的题解都有dp的做法,这个周也终于有机会亲身领略一下dp了

m0_64476152的博客 128

【知识分享】单端到混合S参数转换指南

信号完整性(SI)工程师几乎总是必须使用S参数,因为许多的高速接口和行业标准都正在转向串行链路架构,并使用基于S参数测量的频域限制指标,了解其工作过程将会很有意义。

一只豌豆象的博客 1580

工业预测性维护实战:振动分析+Transformer预警系统构建指南

摘要:本文聚焦工业设备预测性维护难题,提出基于振动分析与Transformer模型的全栈解决方案。通过低成本硬件选型(单传感器¥380)实现设备振动信号实时采集,利用边缘计算单元完成特征工程(RMS、峰度、峰值频率提取),并在云端部署Transformer时序模型进行异常预警。某风电龙头企业实践显示,系统将故障误报率从38%降至6%,维护成本降低58%,非计划停机时长减少87%。文中提供完整的边缘端特征提取代码、云端模型架构及实施流程,适配ISO 13373振动分析标准,为制造业设备健康管理提供可复用的工程

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 627

虚树总结

学习之前的例题 在学虚树之前,先来看一道题: 洛谷P2495 [SDOI2011]消耗战https://www.luogu.org/problemnew/show/P2495 大致题意是这样的,现在有n个点,n-1条带权边的树,有m个询问,每个询问,给出k个点,(其中不包含1号节点),要删除一些边使得1号点与给出的点不连通,求删除边和的最小值。 乍一看,是不是觉得显然是树形dp呢,而且树形...

zhouyuheng2003的博客 5825

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

状态压缩动态规划 - 总结【普及+,提高-】

状态压缩动态规划是一类特殊的动态规划,通常有一维用来表示一个二进制状态。状态压缩,顾名思义,就是把原来要一个bool数组表示状态压缩到一个int变量里。围绕状压DP,我们将介绍它的前世今生,领略状压DP的特点、技巧、应用。 Part 1 特点 状压DP的最显著特点就是n一般不会超过20,这样你才能状压啊。 其次,状压DP经常会被用来解决类似于全排列的问题,这里以2008年宁波市初中组的导...

Qiubo123456789的博客 464

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

HDU 1028 Ignatius and the Princess III

Ignatius and the Princess IIITime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4658

Dwylkz 798

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

专题十八_动态规划_斐波那契数列模型_路径问题_算法专题详细总结

这个时候,不但要多开一行,还要多开两列,将左右两列都设置成INT_MAX,因为本来这两列是不存在的,但是为了在遍历上一行的三个位置的时候会出现越界情况,所以,多开两列,设置成最大值,这样就不会出现越界和乱取值的情况,这样怎么取,都是在ma原数组里面的值;dp[0][1] 和 dp[1][0]里面最小的一个再加上grid[0][0],显然这是绝对不可以的,因为dp[1][1]这个位置就只是只应该有自己原本的那个数,所以dp[0][1] 和 dp[1][0]都应该初始化为0,其他位置都初始化为INT_MAX;

2301_80636070的博客 1440

HDU 1028 Ignatius and the Princess III .

Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4658    Accepted Submission(s): 3263 Problem Description "Well,...

Dwylkz 167

字符串相邻不同排列计数:从容斥原理到算法竞赛实战

在字符串处理与组合数学领域,计算一个字符串的所有不同排列是一个基础问题。其核心原理涉及多重集的排列数公式,即总排列数为 N! / (Π ci!)。当引入“相邻字符不能相同”这类常见约束时,问题的技术价值便得以凸显,它直接关联到去重、调度与编码等实际应用场景。为了高效求解此类计数问题,暴力枚举所有排列并检查的方法在字符串长度较大时不可行,必须借助更高级的算法思想。容斥原理提供了一种优雅的解决方案,它将“无相邻相同”的计数转化为对“至少存在某些字母内部相邻”的子集进行带符号的求和,从而将复杂度从阶乘级降至指数级

weixin_34056162的博客 475

noip2017

2017 11.10 历经四个小时的艰苦跋涉,第三次到衢州府。 心情也和去年大不相同了。 珍惜吧。 2017 11.11 到二中。 第一次发现图书馆的字是孔祥楷题的。他是孔子75代嫡长孙。 高宗南渡时,衍圣公孔端友奉孔庙神主到浙江,赐第衢州,遂为南宗孔氏。大金亦封孔氏后人为北宗衍圣公。大元混一中夏,南北两宗合二为一。 后来蒋公南渡,孔德成随其到台湾。 于是便进了考场。 看了看T

Donald_TY的专栏 1506

Android硕二面试阿里3面被P8架构师吊打,不甘!复盘狂啃底层技术,拿下阿里P6+offer

前言 人人都有大厂梦,对于程序员来说,BAT为首的一线互联网公司肯定是自己的心仪对象,毕竟能到这些大厂工作,不仅薪资高待遇好,而且能力技术都能够得到提升,最关键的是还能够给自己镀上一层金,让人瞻仰。 同样的,我自己的个人目标也是阿里,但之前一直在一家小公司,一呆就是好几年,现在通过不断学习和实践,提升了自己很多,也有了信心来阿里挑战。下面,就是我这次面试阿里P6的一些经历和心得。 阿里P6岗面试经历 这次阿里的面试经历实在太紧张+刺激+尴尬了,面试前还自信满满,面试后被吊打得怀疑人生。整个流程是四面,前

1 426
上一篇: 费解的开关-递推
下一篇: 蓝桥四平方和-枚举||二分||哈希
CodeSlogan
博客等级 码龄6年 4227粉丝 130原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeSlogan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值