【算法】蓝桥杯dfs深度优先搜索之排列组合总结

前言

  上一篇文章 → 《【算法】蓝桥杯dfs深度优先搜索之凑算式总结》

  为了重申感谢之意,再次声明下文的大部分灵感均来自于【CSDN】梅森上校《JAVA版本:DFS算法题解两个例子(走迷宫和求排列组合数)》
  强烈推荐大家去上面那篇文章看看,写的很好。
  下面我会列出蓝桥杯第六届B组省赛第7题、第七届第5题、第八届第4题,共3道题。

  因为他们都是:排列组合。

正文

【第一道题】

牌型种数
  这道题可以强制转为昨天的“凑算式”类型。
  首先,强调一下题意,总共13种牌A到K,每种可以选0到4张,总共选出13张,两个13如果简单表示的话就是2 13,其中13也可以用大写的字母B表示,隐晦的透露了这道题的内涵。
  如果你还能想起来昨天“凑算式”的思路的话,那么上来第一件事肯定就是设置一个数组了
  下图是我昨天在最后一题做的总结,对于这道题来说,也适合。
步骤
  第一件事,显然这个数组的长度为13,因为我们要存13种牌,数组中只存0到4之间的数。

public static int[] a = new int[13];

  第二件事,这里不涉及到数字重用与否,略过。
  第三件事,定义dfs方法,还是和昨天一样,就传一个index参数

public static void dfs(int index)

  第四件事,写递归结束条件,这里就是index == 13,越界,代表A到K我们已经取完了,接下来就是要统计一下总数是不是13张。如果是的话,就算一种,count++。

// 递归结束条件
if(index == 13) {
   
   
	int sum = 0;
	for(int i : a) {
   
   
		sum += i;
	}
	if(sum == 13) {
   
   
		count++;
	}
	return; //递归结束一定要有return啊,没有return不叫递归结束
}

  第五件事,还未凑齐,深搜。a[]数组总共13个位置,每个位置是0到4中的一个数。代码如下:

// 搜索
for(int i=0; i<=4; i++) {
   
   
	a[index] = i;
	dfs(index+1); 
}

【完整代码】

public class 牌型种数dfs {
   
   
	public static int count = 0 ;
	public static int[] a = new int[13];
	public static void dfs(int index) {
   
   
		if(index == 13) {
   
   
			int sum = 0;
			for(int i : a) {
   
   
				sum += i;
			}
			if(sum == 13) {
   
   
				count++;
			}
			return;
		}
		// 搜索
		for(int i=0; i<=4; i++) {
   
   
### 蓝桥杯 C++ 深度优先搜索 (DFS) 算法 示例代码与解思路 #### 一、深度优先搜索 (DFS) 的基本概念 深度优先搜索是一种经典的图遍历算法,通常通过递归来实现。其主要特点是尽可能深地探索每一个分支节点,在遇到无法继续前进的情况时回溯到上一层并尝试其他路径[^1]。 #### 二、蓝桥杯中的 DFS 应用场景 在蓝桥杯竞赛中,DFS 常用于解决组合问、全排列问以及约束满足问(如数独)。这类目往往需要枚举所有可能的状态,并验证每种状态是否符合条件。例如,给定一组数字,找出所有的不重复组合;或者在一个网格中填入特定数值以满足某些条件[^2]。 #### 三、示例代码解析 以下是基于蓝桥杯典型问的一个简单例子——从 `n` 个不同整数中选取 `m` 个组成无序集合的所有可能性: ```cpp #include <cstdio> #include <cstring> using namespace std; const int N = 30; int n, m; int way[N]; void dfs(int u, int start) { if (u > m) { // 边界条件:当已经选择了足够的数量时打印结果 for (int i = 1; i <= m; ++i) { printf("%d ", way[i]); } puts(""); return; } for (int i = start; i <= n; ++i) { // 枚举当前可选的数字 way[u] = i; // 记录当前选择 dfs(u + 1, i + 1); // 进一步处理下一位的选择 way[u] = 0; // 回溯操作,清除标记以便后续计算 } } int main() { scanf("%d %d", &n, &m); dfs(1, 1); // 开始递归过程 return 0; } ``` 上述程序实现了从 `[1..n]` 中选出 `m` 个不同的数的所有方案。其中,`dfs()` 函数的核心逻辑在于逐步构建候选序列,并利用递归完成对剩余位置的填充。每当到达目标长度时即输出当前的结果集。 #### 四、具体应用案例分析 另一个常见的应用场景是在九宫幻方方面。此问是要求将 1 至 9 排列成一个 3×3 方阵使得每一行、列及两条对角线上的三个数之和相等。下面展示了一个简化版的伪代码框架来说明如何运用 DFS 来求解此类问: ```cpp bool check(); // 定义辅助函数判断当前布局是否合法 void solve(); // 初始化变量... solve(); if (!check()) return; // 如果不符合规则则停止进一步扩展该分支 for (...) { // 尝试放置新的元素 place_element(...); solve(); // 继续深入寻找更多可行解 remove_last(); // 清理最后的操作准备测试新情况 } ``` 这里的关键点在于设计合理的剪枝策略减少不必要的穷尽搜索次数从而提高效率。 #### 五、总结 对于参加蓝桥杯比赛的学生来说,熟练掌握 DFS 技巧是非常重要的。这不仅涉及基础理论知识的学习,还需要不断实践各种实际编程挑战项目积累经验。只有这样才能够灵活应对比赛中可能出现的各种复杂情形。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值