抽象深度优先搜索:八皇后

八皇后问题是一个经典的问题, 在一个8 × 8 的棋盘上, 每行刚好放置一个并不能互相攻击(同一行,同一列,同一斜线上的皇后都会自动攻击)。

上图就是一个合法的八皇后的解。

利用数组标记已筛选皇后的同一行,同一列,同一斜线上, 那么同一行,同一列,同一斜线上的位置将不能放置皇后。

同一行,同一列的标记,但最难处理的是同一斜线的标记, 可以通过暴力枚举,但有一种更巧妙地方法。

 

这条对角线的位置的行加列的值相同, 都是4。

即 0 + 4 = 1 + 3 = 2 + 2 =  3 + 1 = 4 + 0 = 4

而这样的对角线的位置的坐标的行减去列的值也是相同的, 都是 - 2。
接下来可以判断第 c 列第 i 行的位置是否可以放下皇后,在这之前我们要标记。

标记列 row[ i ] = ture;

标记第一条对角线  x1[ c+i ] = true;

标记第二条对角线 x2[ c - i + 8 ] = true;

row[i] = x1[c+i] = x2[c-i+8] = true;

注意:回溯要取消标记

row[i] = x1[c+i] = x2[c-i+8] = false;

然后写个布尔类型的check函数来判断当前位置到底能不能放皇后

    bool check(int c, int i){
        return !row[i] && !x1[c+i] && !x2[c-i+8];
    }

开始搜索。

        for(int i=0; i<8; i++){
            if(check(c, i)){
                row[i] = x1[c+i] = x2[c-i+8] = true;
                dfs(c+1);
                row[i] = x1[c+i] = x2[c-i+8] = false;
            }
        }

最后设定边界条件,即递归出口。

如果已经填完前8列, 就可以对结果ans加1

        if(c==8){
            ans++;
            return;
        }

整个代码如下:

    #include <iostream>
    using namespace std;
    int ans = 0;
    bool row[10], x1[20], x2[20];
    bool check(int c, int i){
        return !row[i] && !x1[c+i] && !x2[c-i+8];
    }
    void dfs(int c){
        
        if(c==8){
            ans++;
            return;
        }
        for(int i=0; i<8; i++){
            if(check(c, i)){
                row[i] = x1[c+i] = x2[c-i+8] = true;
                dfs(c+1);
                row[i] = x1[c+i] = x2[c-i+8] = false;
            }
        }
    }
    int main() {
        
        dfs(0);
        cout<<ans<<endl;
        
        return 0;    
    }
---------------------
作者:zspfd
来源:CSDN
原文:https://blog.csdn.net/qq_43780750/article/details/88913326
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-07-18 19:39  天涯海角路  阅读(149)  评论(0)    收藏  举报