当前位置:   article > 正文

DFS算法(深度优先搜索)_void dfs

void dfs

1. 5种形式:

        a. 排序树:孩子不与祖先重复

        b. 组合树:孩子大于父亲

        c. 子集树:左孩子为0,右孩子为1

        d. 拆分树:孩子>=父亲

        e. 搜索树:孩子不与祖先重复

注:黄色点是返回时的标注。

2. 判答案的两种方法

a. 判孩子(当根节点是虚空的时候,比如子集树,排列树,拆分树,组合树)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define N 1000//问题的规模
  4. void dfs(int k);//第k层/代/步
  5. int ans[N];//记录答案
  6. int vis[N];//标记变量,去重
  7. int main()
  8. {
  9. return 0;
  10. }
  11. void dfs(int k)
  12. {
  13. for(int i=1; i<=N; i++)//枚举第k代的所有孩子的线索
  14. {
  15. //生成孩子(用i表示出孩子)
  16. if()//判孩子的合法性(符合约束条件并且不重复)
  17. {
  18. //保存孩子
  19. //标记孩子
  20. if()//如果孩子是答案就输出(判孩子法)
  21. {
  22. }
  23. else//如果孩子不是答案,继续从下一代找
  24. {
  25. }
  26. //取消标记
  27. }
  28. }
  29. }

b. 判父亲(当根节点不是虚空的时候,比如搜索树)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define N 1000//问题的规模
  4. void dfs(int u);//u为父亲结点
  5. int ans[N];//记录答案
  6. int vis[N];//标记变量,去重
  7. int main()
  8. {
  9. return 0;
  10. }
  11. void dfs(int u)
  12. {
  13. //保存父亲
  14. //标记父亲
  15. if()//如果父亲是答案就输出(判父亲法)
  16. {
  17. //输出答案
  18. }
  19. else//如果父亲不是答案,继续从下一代找
  20. {
  21. for(int i=1; i<=N; i++)//枚举第u代的所有孩子的i
  22. {
  23. //生成孩子
  24. if()//判孩子合法性
  25. {
  26. dfs(i);//递归搜索u的孩子i
  27. }
  28. }
  29. }
  30. //取消标记
  31. }

3. 代码

a. 排序树

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define N 1000//问题的规模
  4. void dfs(int k);//第k层/代/步
  5. int ans[N];//记录答案
  6. int vis[N];//标记变量,去重
  7. int n;
  8. int main()
  9. {
  10. cin>>n;
  11. dfs(1);
  12. return 0;
  13. }
  14. void dfs(int k)
  15. {
  16. for(int i=1; i<=n; i++)//枚举第k代的所有孩子的线索
  17. {
  18. //生成孩子(用i表示出孩子)
  19. if(vis[i]==0)//判孩子的合法性(符合约束条件并且不重复)
  20. {
  21. //保存孩子
  22. ans[k]=i;
  23. //标记孩子
  24. vis[i]=1;
  25. if(k>=n)//如果孩子是答案就输出(判孩子法)
  26. {
  27. for(int j=1; j<=k; j++)
  28. {
  29. cout<<ans[j];
  30. }
  31. cout<<endl;
  32. }
  33. else//如果孩子不是答案,继续从下一代找
  34. {
  35. dfs(k+1);
  36. }
  37. //取消标记
  38. vis[i]=0;
  39. }
  40. }
  41. }

b. 组合树

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define N 1000//问题的规模
  4. void dfs(int k);//第k层/代/步
  5. int ans[N];//记录答案
  6. int vis[N];//标记变量,去重
  7. int n, r;//从n个数里面取r个数进行组合
  8. int main()
  9. {
  10. cin>>n>>r;
  11. dfs(1);
  12. return 0;
  13. }
  14. void dfs(int k)
  15. {
  16. for(int i=1; i<=n; i++)//枚举第k代的所有孩子的线索
  17. {
  18. //生成孩子(用i表示出孩子)
  19. if(i>ans[k-1])//判孩子的合法性(符合约束条件并且不重复)
  20. {
  21. //保存孩子
  22. ans[k]=i;
  23. //标记孩子
  24. if(k>=r)//如果孩子是答案就输出(判孩子法)
  25. {
  26. for(int j=1; j<=k; j++)
  27. {
  28. cout<<ans[j];
  29. }
  30. cout<<endl;
  31. }
  32. else//如果孩子不是答案,继续从下一代找
  33. {
  34. dfs(k+1);
  35. }
  36. //取消标记
  37. }
  38. }
  39. }

c. 子集树

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define N 1000//问题的规模
  4. void dfs(int k);//第k层/代/步
  5. int ans[N];//记录答案
  6. int main()
  7. {
  8. dfs(1);//从第一步开始
  9. return 0;
  10. }
  11. void dfs(int k)
  12. {
  13. for(int i=0; i<=1; i++)//枚举第k代的所有孩子的线索
  14. {
  15. //生成孩子(用i表示出孩子)
  16. if(1)//判孩子的合法性(符合约束条件并且不重复)
  17. {
  18. //保存孩子
  19. ans[k]=i;
  20. //标记孩子
  21. if(k>=4)//如果孩子是答案就输出(判孩子法)
  22. {
  23. for(int j=1; j<=k; j++)
  24. {
  25. cout<<ans[j];
  26. }
  27. cout<<endl;
  28. }
  29. else//如果孩子不是答案,继续从下一代找
  30. {
  31. dfs(k+1);
  32. }
  33. //取消标记
  34. }
  35. }
  36. }
  37. /*
  38. 输出:0表示不选,1表示选择
  39. 0000
  40. 0001
  41. 0010
  42. 0011
  43. 0100
  44. 0101
  45. 0110
  46. 0111
  47. 1000
  48. 1001
  49. 1010
  50. 1011
  51. 1100
  52. 1101
  53. 1110
  54. 1111
  55. */

d. 拆分树

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define N 1000//问题的规模
  4. void dfs(int n, int k);//第k层/代/步
  5. int ans[N];//记录答案
  6. int main()
  7. {
  8. ans[0]=1;//初始化时,一定要将ans[0]设成1,因为所有的孩子都必须>=1
  9. dfs(5, 1);
  10. return 0;
  11. }
  12. void dfs(int n, int k)
  13. {
  14. for(int i=1; i<=n; i++)//枚举第k代的所有孩子的线索
  15. {
  16. //生成孩子(用i表示出孩子)
  17. if(i>=ans[k-1])//判孩子的合法性(符合约束条件并且不重复)
  18. {
  19. //保存孩子
  20. ans[k]=i;
  21. //标记孩子
  22. n-=i;
  23. if(n==0)//如果孩子是答案就输出(判孩子法)
  24. {
  25. for(int j=1; j<=k; j++)
  26. {
  27. cout<<ans[j]<<" ";
  28. }
  29. cout<<endl;
  30. }
  31. else//如果孩子不是答案,继续从下一代找
  32. {
  33. dfs(n,k+1);
  34. }
  35. //取消标记
  36. n+=i;
  37. }
  38. }
  39. }

e. 搜索树(找起点到终点的所有路径)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define N 1000//问题的规模
  4. int n,m;//n点,m边
  5. vector<int> a[N];//动态数组存储图
  6. void dfs(int u, int k);//u为父亲结点,第k步
  7. int ans[N];//记录答案
  8. int vis[N];//标记变量,去重
  9. //找到从起点到终点的所有路径
  10. int start=0, target=2;
  11. int main()
  12. {
  13. cin>>n>>m;
  14. for(int i=1; i<=m; i++)
  15. {
  16. int u, v;
  17. cin>>u>>v;
  18. a[u].push_back(v);
  19. a[v].push_back(u);
  20. }
  21. dfs(start,1);
  22. return 0;
  23. }
  24. void dfs(int u, int k)
  25. {
  26. //保存父亲
  27. ans[k]=u;
  28. //标记父亲
  29. vis[u]=1;
  30. if(u==target)//如果父亲是答案就输出(判父亲法)
  31. {
  32. //输出答案
  33. for(int i=1; i<=k; i++)
  34. {
  35. cout<<ans[i]<<" ";
  36. }
  37. cout<<endl;
  38. }
  39. else//如果父亲不是答案,继续从下一代找
  40. {
  41. for(int i=0; i<a[u].size(); i++)//枚举第u代的所有孩子的i
  42. {
  43. int v=a[u][i];//u的第i个孩子
  44. if(vis[v]==0)
  45. {
  46. dfs(v,k+1);//递归搜索u的孩子i
  47. }
  48. }
  49. }
  50. //取消标记
  51. vis[u]=0;
  52. }
  53. /*
  54. 5 7
  55. 0 1
  56. 0 3
  57. 0 4
  58. 1 2
  59. 1 4
  60. 2 3
  61. 3 4
  62. */

4. 实例

1317组合树

1318拆分树

1212搜索树

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define N 25//问题的规模
  4. void dfs(int ii, int jj, int k);//u为父亲结点
  5. int vis[N][N];//标记变量,去重
  6. char a[N][N];
  7. int number[26];
  8. int maxl=0;
  9. int r,s;
  10. int di[4]= {-1,1,0,0};
  11. int dj[4]= {0,0,-1,1};
  12. int main()
  13. {
  14. cin>>r>>s;
  15. for(int i=0; i<r; i++)
  16. {
  17. for(int j=0; j<s; j++)
  18. {
  19. cin>>a[i][j];
  20. }
  21. }
  22. dfs(0,0,1);
  23. cout<<maxl;
  24. return 0;
  25. }
  26. void dfs(int ii,int jj,int k)
  27. {
  28. //保存父亲
  29. //标记父亲
  30. vis[ii][jj]=1;
  31. number[a[ii][jj]-'A']=1;
  32. if(k>maxl)//如果父亲是答案就输出(判父亲法)
  33. {
  34. //输出答案
  35. maxl=k;
  36. }
  37. for(int i=0; i<4; i++)//枚举第u代的所有孩子的i
  38. {
  39. //生成孩子
  40. int ni=ii+di[i];
  41. int nj=jj+dj[i];
  42. if(ni>=0 && ni<r && nj>=0 && nj<s && vis[ni][nj]==0 && number[a[ni][nj]-'A']==0)//判孩子合法性
  43. {
  44. dfs(ni, nj, k+1);//递归搜索u的孩子i
  45. }
  46. }
  47. //取消标记
  48. vis[ii][jj]=0;
  49. number[a[ii][jj]-'A']=0;
  50. }

1213排列树

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define N 1000//问题的规模
  4. void dfs(int k);//第k层/代/步
  5. int ans[N];//记录答案
  6. int vis[N];//标记变量,去重
  7. int n;
  8. int cnt;
  9. int check(int k, int i);
  10. int main()
  11. {
  12. n=8;
  13. dfs(1);
  14. return 0;
  15. }
  16. void dfs(int k)
  17. {
  18. for(int i=1; i<=n; i++)//枚举第k代的所有孩子的线索
  19. {
  20. //生成孩子(用i表示出孩子)
  21. if(vis[i]==0 && check(k,i)==1)//判孩子的合法性(符合约束条件并且不重复)
  22. {
  23. //保存孩子
  24. ans[k]=i;
  25. //标记孩子
  26. vis[i]=1;
  27. if(k>=n)//如果孩子是答案就输出(判孩子法)
  28. {
  29. cnt++;
  30. cout<<"No. "<<cnt<<endl;
  31. for(int j=1; j<=k; j++)
  32. {
  33. for(int p=1; p<=k; p++)
  34. {
  35. if(p==ans[j])
  36. {
  37. cout<<1<<" ";
  38. }
  39. else
  40. {
  41. cout<<0<<" ";
  42. }
  43. }
  44. cout<<endl;
  45. }
  46. }
  47. else//如果孩子不是答案,继续从下一代找
  48. {
  49. dfs(k+1);
  50. }
  51. //取消标记
  52. vis[i]=0;
  53. }
  54. }
  55. }
  56. int check(int k, int i)
  57. {
  58. for(int j=1; j<k; j++)
  59. {
  60. if(ans[j]==i)
  61. {
  62. return 0;//在同一列返回0
  63. }
  64. }
  65. for(int j=1; j<k; j++)
  66. {
  67. if(k-j==ans[j]-i || k-j==i-ans[j])
  68. {
  69. return 0;//在同对角线上返回0
  70. }
  71. }
  72. return 1;
  73. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/596601
推荐阅读
相关标签
  

闽ICP备14008679号