深度优先搜索
Depth First Search,简称DFS:一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(n!)。
基本框架
void dfs(int step) {
if (到达目的地) { //目标状态
输出解;
} else {
for (int i=1; i<=子状态数; i++) {//产生式
if (满足条件) {//扩展条件
保存结果;
dfs(step+1); //下一步
回溯;
}
}
}
}
void dfs(int step) {
for (int i=1; i<=子状态数; i++) {
if (满足条件) {
保存结果;
if (到达目的地) 输出解;
else dfs(step+1); //下一步
回溯;
}
}
}
发明者
深度优先搜索是由Jonh E. Hopcroft 和Robert E. Tarjan发明的。在1971~1972年,在加利福尼亚大学研究图的连通性和平面性时发明的。他们因此获得了1986年的图灵奖。
例题(一维)
1317:【例5.2】组合的输出
【题目描述】
排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r≤n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。
现要求你用递归的方法输出所有组合。
例如n=5,r=3,所有组合为:
1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5
【输入】
一行两个自然数n、r(1<n<21,1≤r≤n)。
【输出】
所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素占三个字符的位置,所有的组合也按字典顺序。
【输入样例】
5 3
【输出样例】
1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5
AC代码参考
#include <bits/stdc++.h>
using namespace std;
int n,r;
int a[24], vis[24];
void dfs(int step) {
//边界
if (step==r+1) {
//输出解
for (int i=1; i<=r; ++i) cout<<setw(3)<<a[i];
cout<<endl;
return ;
}
for (int i=1; i<=n; ++i) {
if (!vis[i] && i>a[step-1]) { //条件
a[step]=i;
vis[i]=1;
dfs(step+1);
vis[i]=0;
}
}
}
int main() {
//解绑
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>r;
dfs(1);
return 0;
}