n皇后 - 位运算版

 n皇后问题是大家在递归里会碰到的一个经典问题。以前高中我学DFS的时候,老师首先让我看的就是八皇后。

不过这皇后的时间复杂度大家可想而知了。而接下来的位运算将这个效率重新提到一个高度。

我是以前在Matrix67大牛那里学的,最近数据结构实验刚好碰到n皇后,就在这里“复述”一遍吧。

Code:
  1. void doans(int r, int ld, int rd)  
  2. {  
  3.     if(r != uplimit)  
  4.     {  
  5.         int pos = uplimit & ~(r | ld | rd);  
  6.   
  7.         while(pos != 0)  
  8.         {  
  9.             int p = pos & (~pos + 1);  
  10.             pos -= p;  
  11.             doans(r + p, (ld + p) << 1, (rd + p) >> 1);  
  12.         }  
  13.     }  
  14.     else sum++;  
  15. }  

乍一看有点模糊吧?没错,这就是n皇后的递归函数了。我们一个个来解析。

首先uplimit是(1 << n) - 1,如果n是8的话uplimit就是255,看做二进制就是11111111。聪明的人一看就知道了,这里每一位就代表一个皇后。

而r代表每一列能放与否,如10001110就代表第2、3、4、8个能放。

所以开始一个if来判断皇后放齐了没。如果齐了,显然r也要等于11111111。

还有ld和rd分别是对角线的各位能放与否。

我们来看看下图(From Matrix67):

  

假设我们已经递归到第三行了(左图),这里可以看出r为101010也就是说二、四、六可以放。ld是100100(蓝色线),二、三、五、六可以放,rd为000111,。

好的,那么哪几个可以放呢?我们将r、ld、rd或运算一遍(或者r有或者ld有或者rd有),得到101111,也就是说这三个合起来的话就只能放第二格了。然后我非运算一遍,得到的是010000,非运算之后1代表可以放,0代表不可以放了。然后我们再与运算一遍就得到可以放的位置了:010000。

下一步,如果能放的位置不是0的话我们就开始放:

Code:
  1. int p = pos & (~pos + 1);  

这一句我们可以用

Code:
  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值