C++深度优先搜素
深度优先搜索特点:穷举所有情况、全排列==完全图、顶点数最好小于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 对应蓝桥云课 排列序数 代码见下
#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 对应蓝桥云课 十位数宝藏代码 代码见下
#include <iostream>
using namespace std;#define maxn 10int 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 对应蓝桥云课带分数, 代码见下
#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;
}