目录
DFS
实现数字全排列
N 皇后问题
DFS
算法的理解
-
优先考虑深度,换句话说就是一条路走到黑,直到无路可走的情况下,才会选择回头,然后重新选择一条路。空间复杂度:O(h)和高度成正比
-
不具有最短路性
DFS板子
DFS没有固定的代码板子,只有一个思路如下所示:
check函数可以用布尔数组代替,达到优化的目的
int check(参数)
{if(满足条件)return 1;return 0;
}void dfs(int step) //step表示深度搜索的深度增加,也就是图中节点
{处理递归的边界{相应操作}for循环迭代途中所有元素{判断满足check条件标记状态继续下一步dfs(step+1)//深度加深恢复初始状态(回溯的时候要用到)修改为原始状态,通过对每个元素的状态修来来完成回溯的操作。}
}
实现数字全排列
这道题并不是标准的使用 dfs 算法搜索图中的点,只是因为对每个位置的数字选择符合递归的特点,所以可以使用递归来解决问题。使用一个数据记录遍历一条到底的路径。
#include <iostream>
using namespace std;const int N=10;
int n;
int a[N];
bool state[N];void dfs(int u)//u:表示搜索的节点
{//边界情况处理if(u>n){for(int i=1;i<=n;i++) printf("%d ",a[i]);printf("\n");}//一般情况for(int i=1;i<=n;i++){if(!state[i]){state[i]=1;a[u]=i;dfs(u+1);//搜索下一个节点state[i]=0;//状态回溯}}
}int main()
{cin>>n;dfs(1);//从根节点开始搜索return 0;
}
N 皇后问题
和数字全排列一样,其中解决问题的思路和dfs很像。
按行回溯, 时间复杂度O(n!)
#include<iostream>
using namespace std;const int N=20;
int n;
char g[N][N];
bool col[N],dg[N],udg[N];void dfs(int u)
{if(u==n){// 等价于cout << g[i] << endl;for(int i=0;i<n;i++) puts(g[i]);puts("");return;}for(int i=0;i<n;i++){// 对于斜线,反斜线的标记是利用率映射的思想// 剪枝(对于不满足要求的点,不再继续往下搜索) // udg[n - u + i],+n是为了保证下标非负if(!col[i] && !dg[n-u+i] && !udg[u+i]){col[i]=dg[n-u+i]=udg[u+i]=1;g[u][i]='Q';dfs(u+1);col[i]=dg[n-u+i]=udg[u+i]=0;g[u][i]='.';}}
}int main()
{cin>>n;for(int i=0;i<n;i++)for(int j=0;j<n;j++)g[i][j]='.';dfs(0);return 0;
}
DFS是优先考虑深度搜索,之后再进行回溯。
递归函数负责往深度走,递归函数调用完后,清除标记,for循环起到在每一层遍历的作用
这里的两道dfs问题都是全排列问题,对当前位置的元素选取是需要需要记录与抹除状态。