普通搜索之DFS

作者: Chuck_Hu | 来源:发表于2017-05-12 09:14 被阅读14次

    深度优先搜索(DFS)和广度优先搜索(BFS)是搜索问题中比较常见的方法。此篇介绍DFS算法思想。
    现有n个点,m条边,每条边按照起点和终点输入。为表示点与点之间存在边,需要建立一个邻接矩阵a[ n ] [ n ],a[ i ] [ j ]=1表示 i 与 j 两点间存在边,反之为0(邻接矩阵限于小数据量)。另外还需设一个一维数组vis[ n ],vis[i]==1表示第 i 个节点已被访问过,无需再访问。

    深度优先遍历遵循两步:

    ①访问节点 i 若vis[ i ]=0,则 j 从1 开始只要a[ i ][ j ]=1&&vis[ j ]=0便访问节点 j 重复上述步骤直到没有点都不符合条件跳出循环(!!!注意每访问一个节点 j 务必将vis[ j ]=1)。
    ②遍历vis[ ]数组,若还存在尚未访问的节点侧从该点开始重复步骤①。
    可见DFS算法是一个不断递归的过程,只需要一套模板即可,做题时根据题意改动模板
    DFS模板:

    //DFS遍历
    int  a[15][15],n,m,u,v,vis[15];
    void DFS(int v)
    {
        //访问到节点v,输出
        cout<<v<<" ";
        vis[v]=1;     //务必将vis[v]=1,否则会重复遍历
        for(int i=1;i<=n;i++)
        {
            //如若节点v到节点i存在边且节点i尚未被访问过,从i开始重复上述步骤
            if(!vis[i]&&a[v][i]) DFS(i);
        }
    }
    void DFSTravel()
    {
        for(int i=1;i<=n;i++)
            if(!vis[i]) DFS(i); //vis[]中若存在未访问的节点,从他开始深度优先遍历
    }
    int main()
    {
        while(cin>>n>>m)
        {
            //初始化
            for(int i=1;i<=n;i++)
            {
                vis[i]=0;
                for(int j=1;j<=n;j++)
                {
                    a[i][j]=0;
                }
            }
            for(int i=1;i<=m;i++)
            {
                cin>>u>>v;  //输入边的起点终点,邻接矩阵中记录
                a[u][v]=1;a[v][u]=1;
            }
            DFSTravel();
            cout<<endl;
        }
        return 0;
    }
    

    理解模板,接下来给出典例~
    http://poj.org/problem?id=1321
    中文题不解释

    #include <iostream>
    #include <stdio.h>
    #include <memory.h>
    #include <memory.h>
    #include <stdio.h>
    #include <time.h>
    using namespace std;
    
    const int maxnum=9;
    char array[maxnum][maxnum];
    bool row[maxnum];
    bool col[maxnum];
    int cnt;
    int n,k;
    
    bool judge(int i,int j)
    {
        if(!col[j] && !row[i] && array[i][j]=='#')
            return true;
        return false;
    }
    
    void dfs(int currow,int num)
    {
       if(num==k)
       {
           cnt++;
           return ;
       }
       int i,j;
       for(i=currow;i<=n;i++)
       {
           for(j=1;j<=n;j++)
           {
               if(judge(i,j))
               {
                   row[i]=true;
                   col[j]=true;
                   dfs(i+1,num+1);
                   row[i]=false;
                   col[j]=false;
               }
           }
       }
    }
    
    int main()
    {
        int i,j;
        while(scanf("%d%d",&n,&k)!=EOF)
        {
            if(n==-1 && k==-1)
                break;
            getchar();
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=n;j++)
                    scanf("%c",&array[i][j]);
                if(j==n+1) getchar();
            }
    
            cnt=0;
            memset(row,false,sizeof(row));
            memset(col,false,sizeof(col));
            for(i=1;i<=n-k+1;i++)   //首行的开始位置
            {
                for(j=1;j<=n;j++)
                {
                    if(judge(i,j))
                    {
                        row[i]=true;
                        col[j]=true;
                        dfs(i+1,1);
                        row[i]=false;
                        col[j]=false;
                    }
                }
            }
            printf("%d\n",cnt);
        }
        return 0;
    }
    

    其他例题可以在典例类中看。DFS可以出的迷宫题很多。例如POJ2251多维迷宫题。

    相关文章

      网友评论

        本文标题:普通搜索之DFS

        本文链接:https://www.haomeiwen.com/subject/crmatxtx.html