• 排列组合DFS


    深度优先搜索:根据栈的特性,且每个节点只能被访问一次,
    在寻找终点的过程中将当前元素入栈,若遇到死路则弹出栈顶元素,直到某个元素可以继续发散为止;
    从初始节点出发,按预定的顺序扩展到下一个节点,
    然后从下一节点出发继续扩展新的节点,
    不断递归执行这个过程,直到某个节点不能再扩展下一个节点为止。
    此时,则返回上一个节点重新寻找一个新的扩展节点。
    如此搜索下去,直到找到目标节点,或者搜索完所有节点为止。


    深度优先搜索算法框架

    void dfs(int layers)
    {
         if (到达终点)
         {
             输出结果
             return;    
         }

         for (枚举每一种可能情况)
         {
              if (当前选择满足条件)
              {
                   保存结果
                   dfs(layers + 1); 继续更深层递归
              }  
         }
    }

    图的深度优先搜索的核心思想:
    (1)初始化图中所有节点未被访问
    (2)从图中的某个结点s出发,访问u并标记已访问
    (3)依次检查s的所有邻接点v, 如果v未被访问,则从v出发深度优先搜索。

    const int MAXN = 10 + 2;
    struct node {
        int to;
        int next;
    } edge[MAXN*MAXN];

    int head[MAXN];
    bool vis[MAXN];

    int cnt = 0;
    void add(int u, int v)
    {
        edge[cnt].to = v;
        edge[cnt].next = head[u];  // 采用头插法
        head[u] = cnt++;
    }

    void DFS_AL(int s)
    {
        std::cout << s << " ";
        vis[s] = true;
        for (int i = head[s]; ~i; i = edge[i].next)
        {
            int v = edge[i].to;
            if (!vis[v])
                DFS_AL(v);
        }
    }

    int main()
    {
        int arr[][2] = { { 1, 2 },{ 1, 3 },{ 1, 4 },{ 2, 4 },{ 2, 5 },{ 3, 6 },{ 4, 3 },{ 5, 4 },{ 5, 7 },{ 7, 6 } };
        int num = sizeof(arr) / sizeof(arr[0]);
        for (int i = 0; i < num; ++i)
        {
            vis[i] = false;
            head[i] = -1;
        }
        for (int i = 0; i < num; ++i)
            add(arr[i][0], arr[i][1]);

        DFS_AL(1);

        return 0;
    }

    n个数全排列,将问题分层,每层选择一个数

    const int MAXN = 10 + 2;
    bool vis[MAXN];
    int path[MAXN];

    void dfs_perm(int s, int n, int &sum)
    {
        if (s == n+1)
        {
            ++sum;
            for (int i = 1; i <= n; ++i)
                std::cout << path[i] << " ";
            std::cout << std::endl;
            return ;
        }

        for (int i = 1; i <= n; ++i)
        {
            if (!vis[i])
            {    
                vis[i] = true;
                path[s] = i;
                dfs_perm(s+1, n, sum);
                vis[i] = false;
            }
        }
    }

    int main()
    {
        for (int i = 0; i < MAXN; ++i)
        {
            vis[i] = false;
            path[i] = 0;
        }

        int sum = 0;
        dfs_perm(1, 3, sum);
        std::cout << sum << std::endl;

        return 0;
    }

    从n个数中选取m个的组合

    const int MAXN = 10 + 2;
    int path[MAXN];

    void dfs_comb(int s, int n, int m, int &sum)
    {
        if (s > m)
        {
            ++sum;
            for (int i = 1; i <= m; ++i)
                std::cout << path[i] << " ";
            std::cout << std::endl;
            return;
        }

        for (int i = 1; i <= n; ++i)
            if (path[s-1] < i)  // 组合数升序, 故互异,不需要vis[]标识元素是否已经访问
            {
                path[s] = i;
                dfs_comb(s+1, n, m, sum);
            }
    }

    int main()
    {
        int sum = 0, n = 5, m = 3;    
        dfs_comb(1, n, m, sum);
        std::cout << sum << std::endl;

        return 0;
    }

  • 相关阅读:
    RHCE(三、四)NTP时间服务器、SSH远程加密登录
    HTML5期末大作业【红色的电影售票平台网站】web前端 html+css+javascript网页设计实例 企业网站制作
    linux知识复习1-dup dup2
    fastapi_No.18_后台应用
    Android开发之指南针
    LeetCode_前缀树_648.单词替换
    直播邀请函 | 第12届亚洲知识产权营商论坛:共建创新价值 开拓崭新领域
    【知识专栏丨python数分实战】电商数据分析案例
    三驾马车、四大赛道,元宇宙如何领跑数字经济?
    江苏服务器租用:算力服务器适用于哪些场景?
  • 原文地址:https://blog.csdn.net/cai0612123/article/details/126867682