用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;
}

  

原文地址:https://www.cnblogs.com/ya-cpp/p/8249642.html