深搜

这篇博客详细介绍了如何使用递归算法解决全排列、组合等数学问题,包括青藤oj上的多个题目,如全排列问题(#10049)、组合输出(#10277)、自然数和分解(#10119)以及数的划分问题(#160)。通过递归思路,博主阐述了解决这些问题的关键步骤,并提供了相应的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

青藤oj #10049. 全排列问题

题目描述

输出自然数 1 到n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

输入格式

n(1≤n<9)

输出格式

由 1~n 组成的所有不重复的数字序列,每行一个序列。注意,每个数前面输出4个空格,包括第一个数。

思路

用递归每一个数都试一遍,如果没用过就标记为1,如果用过就下一个;
用s存下每一深度记下的数,当深度大于位数时,输出s;
return,从上一步继续往下推;

代码

#include<bits/stdc++.h>
using namespace std;
int a[1000]={
   0},s[1000];
int n;
void dfs(int deep)
{
   
	if(deep==n+1)
	{
   
		for(int i=1;i<=n;i++)
		  cout<<"    "<<s[i];
		cout<<endl;
		return;
	}
	for(int i=1;i<=n;i++)
	{
   
		if(a[i]==1)
		  continue;
		a[i]=1;
		s[deep]=i;
		dfs(deep+1);
		a[i]=0;
	}
	return;
}
int main()
{
   
### C++度优先索(DFS)的实现与应用 #### DFS 的基本概念 度优先索(Depth First Search, DFS)是一种用于遍历或索树或图数据结构的算法。它通过从起始节点开始,沿着一条路径尽可能入地探索,直到无法再前进时才会回溯到上一层节点[^4]。 #### 基本实现方式 在 C++ 中,DFS 可以通过递归或者栈来实现。以下是两种常见的实现方法: ##### 方法一:递归实现 递归是最常用的实现方式之一,代码简洁明了。下面是一个基于邻接表表示的图进行 DFS 遍历的例子: ```cpp #include <iostream> #include <vector> using namespace std; void dfs(int node, vector<vector<int>>& adjList, vector<bool>& visited) { visited[node] = true; cout << node << " "; // 访问当前节点 for (int neighbor : adjList[node]) { // 遍历相邻节点 if (!visited[neighbor]) { // 如果未访问过,则递归调用 dfs(neighbor, adjList, visited); } } } int main() { int n = 5; // 节点数 vector<vector<int>> adjList(n + 1); // 创建邻接表 vector<bool> visited(n + 1, false); // 初始化访问状态数组 // 添加边 adjList[1].push_back(2); adjList[1].push_back(3); adjList[2].push_back(4); adjList[3].push_back(5); cout << "DFS Traversal: "; dfs(1, adjList, visited); // 从节点1开始DFS } ``` ##### 方法二:使用显式栈实现 对于某些场景下可能需要避免递归带来的堆栈溢出风险,可以采用显式栈的方式实现 DFS: ```cpp #include <iostream> #include <vector> #include <stack> using namespace std; void iterativeDfs(int startNode, vector<vector<int>>& adjList, vector<bool>& visited) { stack<int> s; s.push(startNode); while (!s.empty()) { int currentNode = s.top(); s.pop(); if (!visited[currentNode]) { cout << currentNode << " "; // 访问当前节点 visited[currentNode] = true; // 将邻居按逆序压入栈中(保证先访问顺序) for (auto it = adjList[currentNode].rbegin(); it != adjList[currentNode].rend(); ++it) { if (!visited[*it]) { s.push(*it); } } } } } int main() { int n = 5; // 节点数 vector<vector<int>> adjList(n + 1); // 创建邻接表 vector<bool> visited(n + 1, false); // 初始化访问状态数组 // 添加边 adjList[1].push_back(2); adjList[1].push_back(3); adjList[2].push_back(4); adjList[3].push_back(5); cout << "Iterative DFS Traversal: "; iterativeDfs(1, adjList, visited); // 从节点1开始DFS } ``` #### 应用实例 DFS 广泛应用于各种实际问题中,例如迷宫求解、连通分量查找以及拓扑排序等。以下是一些具体的应用案例: ##### 迷宫求解 假设有一个二维网格代表迷宫,其中 `0` 表示障碍物而 `1` 表示可通行区域。可以通过 DFS 来寻找是否存在从起点 `(x_start, y_start)` 到达终点 `(x_end, y_end)` 的路径[^1]: ```cpp bool mazeSearch(int x, int y, vector<vector<int>>& grid, vector<vector<bool>>& visited) { if (x < 0 || y < 0 || x >= grid.size() || y >= grid[0].size() || !grid[x][y] || visited[x][y]) { return false; } if (x == grid.size()-1 && y == grid[0].size()-1) { cout << "Path found!" << endl; return true; } visited[x][y] = true; // 向四个方向尝试移动 if (mazeSearch(x+1, y, grid, visited)) return true; if (mazeSearch(x-1, y, grid, visited)) return true; if (mazeSearch(x, y+1, grid, visited)) return true; if (mazeSearch(x, y-1, grid, visited)) return true; return false; } ``` ##### 组合生成 利用 DFS 枚举所有满足条件的状态组合也是一个典型应用场景。比如给定长度为 `len` 的序列,填充范围 `[1, k]` 内整数值的所有可能性[^3]: ```cpp void generateCombinations(vector<int>& currentCombination, int length, int maxValue) { if (currentCombination.size() == length) { for (int value : currentCombination) { cout << value << ' '; } cout << '\n'; return; } for (int i = 1; i <= maxValue; ++i) { currentCombination.push_back(i); generateCombinations(currentCombination, length, maxValue); currentCombination.pop_back(); // 回溯操作 } } int main() { vector<int> combination; int len = 3, maxVal = 3; generateCombinations(combination, len, maxVal); } ``` #### 总结 以上展示了如何在 C++ 中实现和运用度优先索技术解决不同类型的计算难题。无论是简单的图遍历还是复杂的约束满足问题,DFS 提供了一种通用且强大的工具集。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值