zoukankan      html  css  js  c++  java
  • 八皇后问题的n种解法

     经典的八皇后问题:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

    很早就接触过八皇后问题,最近数据结构作业中又看到了这个题目,仔细研究了一波网上诸位大牛的博客,发现这个问题居然有这么多有趣的优化。

    1.经典的回溯递归解法:

    #include<stdio.h>
    #include<iostream>
    using namespace std;
    //dfs,每行只能放一个元素,遍历每行的每个位置,用一个一维数组记录,最后检查是否符合要求
    int ans; int vis[10]; int abs(int x){ return x > 0 ? x : -x; } bool check(int r,int c){ for(int i = 1;i<r;i++){ if(vis[i] == c) return false; if(vis[i] - c == r - i || vis[i] - c == i - r) return false; } return true; } void dfs(int r){ if(r > 8){ ans++; return; } for(int i = 1;i<=8;i++){ if(check(r,i)){ vis[r] = i; dfs(r+1); vis[r] = 0; } } } main(){ dfs(1); cout<<ans<<endl; }

    2.对角线检查优化

    /*用三个数组记录列,左对角线,右对角线信息,每次判断该位置是否符合要求,只在符合要求位置放置元素。*/
    #include <iostream>
    using namespace std;
    const int maxn=105;
    const int mo=100;
    typedef long long ll;
    int a[maxn],n = 8,ans=0;
    bool b[maxn],c[maxn],d[maxn];
    void sou(int x){
        if(x > n){
            ans++;
            return;
        }
        for(int i = 1;i <= n;i++)if(!(b[i] || c[x+i] || d[x-i+n])){
            b[i] =c [x+i]=d[x-i+n]=true;
            a[x] = i;
            sou(x+1);
            b[i] =c [x+i] = d[x-i+n]=false;
        }
    }
    int main(){
        sou(1);
        cout<<ans;
    }

    3.位运算:

    //算法思想与上一相同,改用三个int来存储信息,采用位运算提取合适位置
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    int board;
    int n;
    int ans = 0;
    void n_queen(int col,int ld,int rd){
        if(col == board){
            ans++;
            return;
        }
        int pos = board & (~(col | ld | rd));
        while(pos){
            int p = pos & (-pos);
            pos = pos - p;
            n_queen(col | p , (ld | p) << 1,(rd | p) >> 1);
        }
    }
    int main(){
        cin>>n;
        board = (1 << n) - 1;
        n_queen(0,0,0);
        cout<<ans<<endl;
    }

    4.十行内的八皇后...

    https://www.zhihu.com/question/28543312

    对知乎上各路大大的炫技佩服的五体投地,更改了一下上一代码,勉强也达到了十行的要求。。。

    #include<iostream>
    int n_queen(int col,int ld,int rd,int board){
        if(col == board) return 1;
        int tot = 0;
        for(int pos = board & (~(col | ld | rd)); pos != 0;pos -= (pos & (-pos))) tot+=n_queen(col | (pos & (-pos)) , (ld | (pos & (-pos))) << 1,(rd | (pos & (-pos))) >> 1,board);
        return tot;
    }
    int main(){
        std::cout<<n_queen(0,0,0,(1<<8)-1);
    }

    小结:断断续续研究了两天各类八皇后写法,感觉自己对位运算的运用加深了一个层次,更大的收获还是知道了自己的渺小,一个原以为十分简单的八皇后都可以衍生出这么多东西,递归的非递归的,全排列搜索的,回溯法的,甚至还有广搜版本的八皇后...,学习之路果然永无止境

  • 相关阅读:
    sqlplus时报Linux-x86_64 Error: 13: Permission denied
    thrift之TTransport层的缓存传输类TBufferedTransport和缓冲基类TBufferBase
    Java实现 蓝桥杯 算法提高 新建Microsoft world文档
    Java实现 蓝桥杯 算法提高 新建Microsoft world文档
    Java实现 蓝桥杯 算法提高 快乐司机
    Java实现 蓝桥杯 算法提高 快乐司机
    Java实现 蓝桥杯 算法提高 队列操作
    Java实现 蓝桥杯 算法提高 队列操作
    Java实现 蓝桥杯 算法提高 文本加密
    Java实现 蓝桥杯 算法提高 合并石子
  • 原文地址:https://www.cnblogs.com/xinghuan/p/6061824.html
Copyright © 2011-2022 走看看