深度优先搜索特点:穷举所有情况、全排列==完全图、顶点数最好小于11、需要哈希表和栈的数据结构基础。
算法描述,第一步,初始化数据结构,全排列在计算过程中,需要利用一个哈希表visited和一个栈stack来记录当前访问过的节点。其中哈希表是为了快速查找某个节点是否被访问,并且执行插入,栈是为了记录顶点的访问顺序。
第二步,顶点访问,依次访问所有顶点,如果发现这个顶点没有在哈希表中,则把它插入哈希表,并且把这个顶点入栈。这样一来,哈希表和栈中,存储的就是本次遍历中存储的点。
第三步,递归调用,利用递归进行调用自身,继续访问下一个节点。
第四步,当本次访问的顶点数等于总顶点数的时候,栈中的元素就代表一个排列,把排列进行输出或者做其他相应的处理。
第五步,回溯,当没有任何顶点需要访问的时候,进行回溯。回溯就是将栈顶元素出栈,并且将这个元素从哈希表中移除
代码分析,
第一步,初始化数据结构
function initData(visited, stack)
visited.clear()
stack.clear()
第二步,框架代码
function dfs(depth, maxDepth)
if depth == maxDepth
print(stack)
return
for i -> (0, maxDepth - 1)
if i not in visited
visited.add(i)
stack.push(i)
dfs(depth+1, maxDepth)
visited.remove(i)
stack.pop()
这个算法时间复杂度为n的阶乘
代码练习 1 对应蓝桥云课 排列序数 代码见下
cpp
#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
using namespace std;
#define maxn 10
string str;
int ans;
int visited[maxn];
int stack[maxn];
int cnt;
string sorted;
void dfs(int depth, int maxDepth){
if(depth == maxDepth){
int i;
for(i=0; i<maxDepth; ++i){
int idx = stack[i];
if(sorted[idx] != str[i]){
break;
}
}
if(i == maxDepth){
ans = cnt;
}
++cnt;
return;
}
for(int i=0; i<maxDepth; ++i){
if(!visited[i]){
visited[i] = 1;
stack[depth] = i;
dfs(depth+1, maxDepth);
visited[i] = 0;
}
}
}
int main()
{
cin >> str;
sorted = str;
sort(sorted.begin(), sorted.end());
memset(visited, 0, sizeof(visited));
cnt = 0;
dfs(0, str.size());
cout << ans << endl;
// 请在此输入您的代码
return 0;
}
代码练习 2 对应蓝桥云课 十位数宝藏代码 代码见下
cpp
#include <iostream>
using namespace std;
#define maxn 10
int visited[maxn];
int stack[maxn];
long long Min = (long long)9876543210;
long long Max = 0;
void dfs(int depth, int maxDepth, long long ans){
if(depth == maxDepth){
if(ans % 11 == 0){
if(ans < Min) Min = ans;
if(ans > Max) Max = ans;
}
return;
}
if(depth == 1){
if(ans == 0){
return;
}
}
for(int i=0; i<maxDepth; ++i){
if(!visited[i]){
visited[i] = 1;
stack[depth] = i;
dfs(depth+1, maxDepth, ans*10 + i);
visited[i] = 0;
}
}
}
int main()
{
dfs(0, 10, 0);
cout << Max - Min << endl;
// 请在此输入您的代码
return 0;
}
代码练习3 对应蓝桥云课带分数, 代码见下
cpp
#include <iostream>
using namespace std;
// #define maxn 10
// int visited[maxn];
// int stack[maxn];
// void dfs(int depth, int maxDepth){
// if(depth == maxDepth){
// // stack存储了[0, maxDepth-1]的全排列
// return;
// }
// for(int i=0; i<maxDepth; ++i){
// if(!visited[i]){
// visited[i] = 1;
// stack[depth] = i;
// dfs(depth+1, maxDepth);
// visited[i] = 0;
// }
// }
// }
#define maxn 10
int N;
int ans;
int visited[maxn];
int pow10[maxn] = {
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000
};
int cnt(int sum){
int ans = 0;
for(int i = 8; i >= 0; --i){
int x = sum / pow10[i];
if(N <= x){
break;
}
int y = N - x;
int z = sum % pow10[i];
for(int j = 1 ; ; ++j){
int fm = z % pow10[j];
int fz = z / pow10[j];
if(fz < fm){
break;
}
if(fz % fm == 0){
if(fz / fm == y){
++ans;
}
}
}
}
return ans;
}
void dfs(int depth, int maxDepth, int sum){
if(depth == maxDepth){
ans += cnt(sum);
// stack存储了[0, maxDepth-1]的全排列
return;
}
for(int i=0; i<maxDepth; ++i){
if(!visited[i]){
visited[i] = 1;
dfs(depth+1, maxDepth, sum*10+(i+1));
visited[i] = 0;
}
}
}
int main()
{
cin >> N;
dfs(0, 9, 0);
cout << ans << endl;
// 请在此输入您的代码
return 0;
}