zoukankan      html  css  js  c++  java
  • 【位运算】高效解决n皇后问题

    面向搜索引擎编程

    #include<bits/stdc++.h>
     
    using namespace std;
     
    // sum用来记录皇后放置成功的不同布局数;upperlim用来标记所有列都已经放置好了皇后。
    long sum = 0, upperlim = 1;
    // 试探算法从最右边的列开始。
    void test(long col, long ld, long rd)
    {
        if (col != upperlim){
            // row,ld,rd进行“或”运算,求得所有可以放置皇后的列,对应位为0,
            // 然后再取反后“与”上全1的数,来求得当前所有可以放置皇后的位置,对应列改为1
            // 也就是求取当前哪些列可以放置皇后
            long pos = upperlim & ~(col | ld | rd);
            while (pos){
                // 拷贝pos最右边为1的bit,其余bit置0
                // 也就是取得可以放皇后的最右边的列
                long p = pos & -pos;//类似树状数组中操作,取一个数二进制的最后一个1
     
                // 将pos最右边为1的bit清零
                // 也就是为获取下一次的最右可用列使用做准备,
                // 程序将来会回溯到这个位置继续试探
                pos -= p;
     
                // row + p,将当前列置1,表示记录这次皇后放置的列。
                // (ld + p) << 1,标记当前皇后左边相邻的列不允许下一个皇后放置。
                // (ld + p) >> 1,标记当前皇后右边相邻的列不允许下一个皇后放置。
                // 此处的移位操作实际上是记录对角线上的限制,只是因为问题都化归一行网格上来解决,所以表示为列的限制就可以了。
                //显然,随着移位,在每次选择列之前进行,原来N×N网格中某个已放置的皇后针对其对角线,上产生的限制都被记录下来了
                test(col + p, (ld + p) << 1, (rd + p) >> 1);
            }
        }else{
            // row的所有位都为1,即找到了一个成功的布局,回溯
            sum++;
        }
    }
     
    int main()
    {
        int n;
        // 因为整型数的限制,最大只能32位,
        // 如果想处理N大于32的皇后问题,需要用bitset数据结构进行存储
        scanf("%d",&n);
        if ((n < 1) || (n > 32)){
            printf(" 只能计算1-32之间
    ");
            exit(-1);
        }
        printf("%d 皇后
    ", n);
        // N个皇后只需N位存储,N列中某列有皇后则对应bit置1。
        upperlim = (upperlim << n) - 1;
        test(0, 0, 0);
        printf("共有%ld种排列
    ", sum);
        return 0;
    }
     
  • 相关阅读:
    gulp模块编译
    微擎数据库表-T
    微信小程序自动识别姓名电话地址
    PHPBase64格式编码图片
    HTML中Data的数据类型
    EPP状态码
    WePay-T
    HTML-T
    PHPNamespace命名空间
    jQuery:jQuery简介
  • 原文地址:https://www.cnblogs.com/Diliiiii/p/9387516.html
Copyright © 2011-2022 走看看