• DFS(深度优先搜索)


    深度优先搜索算法(英语:Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。(直到走不下去才往回走)
    基本模板

     1 int check(参数)
     2 {
     3     if(满足条件)
     4         return 1;
     5     return 0;
     6 }
     7 
     8 void dfs(int step)
     9 {
    10         判断边界
    11         {
    12             相应操作
    13         }
    14         尝试每一种可能
    15         {
    16                满足check条件
    17                标记
    18                继续下一步dfs(step+1)
    19                恢复初始状态(回溯的时候要用到)
    20         }
    21 }   

    实例

    1、全排列(字符串内元素的所有排列方法)(洛谷CF6A与此题类似)

     1 //全排列问题
     2 #include<stdio.h>
     3 #include<string.h>
     4 
     5 int n;
     6 char  a[15];
     7 char re[15];
     8 int vis[15];
     9 //假设有n个字符要排列,把他们依次放到n个箱子中
    10 //先要检查箱子是否为空,手中还有什么字符,把他们放进并标记。
    11 //放完一次要恢复初始状态,当到n+1个箱子时,一次排列已经结束
    12 void dfs(int step)
    13 {
    14     int i;
    15     if(step==n+1)//判断边界
    16     {
    17         for(i=1;i<=n;i++)
    18             printf("%c",re[i]);
    19         printf("
    ");
    20         return ;
    21     }
    22     for(i=1;i<=n;i++)//遍历每一种情况
    23     {
    24         if(vis[i]==0)//check满足
    25         {
    26             re[step]=a[i];
    27             vis[i]=1;//标记
    28             dfs(step+1);//继续搜索
    29             vis[i]=0;//恢复初始状态
    30         }
    31     }
    32     return ;
    33 }
    34 
    35 int main()
    36 {
    37     int T;
    38     scanf("%d",&T);
    39     getchar();
    40     while(T--)
    41     {
    42         memset(a,0,sizeof(a));
    43         memset(vis,0,sizeof(vis));//对存数据的数组分别初始化
    44         scanf("%s",a+1);
    45         n=strlen(a+1);
    46         dfs(1);//从第一个箱子开始
    47     }
    48     return 0;
    49 }

    2、棋盘问题http://acm.sdtbu.edu.cn/vjudge/contest/view.action?cid=2373#problem/A
    问题:在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。

    input: 输入含有多组测试数据。 每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n 当为-1 -1时表示输入结束。 随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。

    output:对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。

    Sample Input

    2 1
    #.
    .#
    4 4
    ...#
    ..#.
    .#..
    #...
    -1 -1
    

    Sample Output

    2
    1
    
     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 
     5 char a[10][10];//棋盘
     6 int vis[10];//标记
     7 int n, k, js = 0;//n行列数k棋子数js方案数
     8 
     9 void dfs(int, int);
    10 
    11 int main()
    12 {
    13     while(EOF != scanf("%d%d", &n, &k)) {
    14         if(n == -1 && k == -1) break;
    15         memset(vis, 0, sizeof(vis));
    16         getchar();
    17         for(int i = 0; i < n; i++) {
    18             gets(a[i]);
    19         }
    20         dfs(0, 0);//从第0行开始找, 已排0个棋子
    21         printf("%d
    ", js);
    22         js = 0;
    23     }
    24 
    25     return 0;
    26 }
    27 
    28 void dfs(int r, int step) {
    29     if(step == k) {//判断边界,此时棋子已经放完
    30         js++;
    31         return;
    32     }
    33     for(int i = r; i < n; i++) {
    34         for(int j = 0; j < n; j++) {
    35             if (a[i][j] == '#' && !vis[j]) {//是棋盘区且没有放棋子
    36                 vis[j] = 1;//表示本列已经放了棋子
    37                 dfs(i + 1,step + 1);//直接从下一行开始,因为不能放在同一行
    38                 vis[j] = 0;//回溯
    39             }
    40         }
    41     }
    42 }

    类似排列组合

    总结一下,用递归法来实现DFS,比较好理解,就一直往下找,知道走不通后在回来尝试其它的地方。一个DFS一般要判断边界,check来判断是否符合相应条件,vis或者book来记录是否已经被用过,递归进行下一步操作。有的时候我们要将标记过的点恢复原来的状态,有时候则不必要恢复(油田问题),要结合具体的问题来分析。

    恢复标记相当于回溯的思想。
    回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

    参考博客raphealguo@CSDN:https://blog.csdn.net/ldx19980108/article/details/76324307

  • 相关阅读:
    数据预处理和特征工程
    批量梯度下降,随机梯度下降,小批量梯度下降
    动态规划和贪心算法的区别
    广告计价方式:CPM,CPC,CPA
    隐语义模型LFM
    windows下安装xgboost
    KMP算法
    sklearn中的SGDClassifier
    JS变量和数据类型
    JS的基本使用 使用外部的JS文件
  • 原文地址:https://www.cnblogs.com/knightoflake/p/12527460.html
Copyright © 2020-2023  润新知