• 用DFS实现全排列 & 八皇后问题


    递归+回溯

    基本思想就是:

    1、用一个标记数组记录当前那些数字已经被用了

    2、枚举第一个位置所有点的可能情况,然后将第一个位置使用的元素进行标记,然后DFS(i,0)

    3、DFS(num, level)要做的事情就是,先将该数放进g[level] = num; (即将当前数放进该层中),然后去遍历vis[] 数组,看那些数还能被使用,不能用的跳过,能用的先标记,再DFS(i,level+1) 再取消标记。DFS()结束的标志是,当填完当前位置元素后,没有元素能被放置,(即所有的元素已经使用完了)这时候就进行回溯。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int n;
    int vis[10];
    int g[10];
    int ans = 0;
    
    void DFS(int num, int level)
    {
        g[level] = num;
    
        if(level == n-1)
        {
            ans ++;
            for(int i = 0; i < n; ++i)
            {
                printf("%d ", g[i]);
            }
            puts("");
            return;
        }
    
        for(int i = 1; i <= n; ++i)
        {
            if(!vis[i])
            {
                vis[i] = 1;
                DFS(i, level+1);
                vis[i] = 0;
            }
        }
    }
    
    int main()
    {
        while(cin >> n)
        {
            ans = 0;
            for(int i = 1; i <= n; ++i)
            {
                memset(vis, 0, sizeof(vis));
                memset(g, 0, sizeof(g));
                vis[i] = 1;
                DFS(i, 0);
                vis[i] = 0;
            }
            printf("n = %d, ans = %d
    ", n, ans);
        }
        return 0;
    }
    

      

    八皇后问题(在一个8*8的棋盘上放置 queue, 要求每行每列,各个对角线不能有两个queue)

    想法:和用DFS写全排列想法类似。用vis_col[] 数组去标记每一列,DFS的过程去一行一行递归,然后回溯。其中就是加了对两个queue是否在一列的判断。

    #include<cstdio>
    #include<cstring>
    #include <cmath>
    
    using namespace std;
    int g[10][10];
    int vis_col[10];
    
    int check(int row, int col)
    {
        for(int i = 0; i < 8; ++i)
        {
            for(int j = 0; j < 8; ++j)
            {
                if(g[i][j] == 1)
                {
                    if(abs(i - row) == abs(j - col))
                        return 1;
                }
            }
        }
        return 0;
    }
    
    
    int ans = 0;
    void DFS(int row, int col)
    {
        g[row][col] = 1;
    
        if(row == 7)
        {
            ans ++;
            for(int i = 0; i < 8; ++i)
            {
                for(int j = 0; j < 8; ++j)
                    printf("%d ", g[i][j]);
                puts("");
            }
            g[row][col] = 0;
    
            return;
        }
    
        for(int i = 0; i < 8; ++i)
        {
            if(!vis_col[i] && !check(row+1, i))
            {
                //printf("%d ", i);
                vis_col[i] = 1;
                DFS(row+1, i);
                vis_col[i] = 0;
            }
        }
    
        g[row][col] = 0;
    }
    
    int main()
    {
        //freopen("out.txt", "w", stdout);
        memset(g, 0, sizeof(g));
        memset(vis_col, 0, sizeof(vis_col));
        for(int i = 0; i < 8; ++i)
        {
    
            vis_col[i] = 1;
            DFS(0, i);
            vis_col[i] = 0;
            puts("");
        }
        printf("ans is %d 
    ", ans);
        return 0;
    }
    

      

  • 相关阅读:
    Go-闭包
    GO-数组与切片
    Go-包
    Go-for循环
    GO-逻辑判断(if,else if,else,switch)
    前后端分离的思考与实践(六)
    前后端分离的思考与实践(五)
    前后端分离的思考与实践(三)
    前后端分离的思考与实践(二)
    前后端分离的思考与实践(一)
  • 原文地址:https://www.cnblogs.com/ya-cpp/p/8249642.html
Copyright © 2020-2023  润新知