使用比特位图解决八皇后问题

八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。(百度百科)

百度百科提到了两种解法:残卷法和深搜,这两种方式相信大家都可以想到。“残卷法”是确定每一步之后将剩余棋盘不可用的位置都标记出来,代码实现比较繁琐;而提到的深搜的方法需要保存额外的信息,也比较麻烦。

这里,我们注意到:8X8棋盘,8皇后,而8正好是一个字节的比特数!利用C语言的位操作可以轻松的实现对此问题条件限制的判断。OK,我们继续分析这个问题,任意两个皇后不能处于同一行、同一列或同一斜线上,那么有条件限制:
a) 每一行只有一个皇后,这样我们每一步可以确定一个皇后的位置,共8步
b) 每一列只有一个皇后,我们可以将已确定的皇后列位置标记出来(按位或),新增的皇后不能处于这些位置
c) 两皇后不能位于同一斜线如何判断?思考如果两皇后在同一斜线,那么固定一个皇后的列位置,将另一个皇后的列位置左移(或右移)两个皇后的行间距,则两皇后位置重合。

有了如上三种条件限制,同样采用深搜的思路,代码就非常容易了。

[cpp] 
view plain
copy

  1. #include <stdio.h>  
  2.   
  3. #define QUEEN_MAX   8  
  4.   
  5. unsigned char chess_board[QUEEN_MAX];  
  6. static int solutions = 0;  
  7.   
  8. void Queen8(int step)  
  9. {  
  10.     int i, j;  
  11.     unsigned char position;  
  12.     if(step == QUEEN_MAX-1)     /* 最后一步 */  
  13.     {  
  14.         position = 0;  
  15.         for(i=0; i<QUEEN_MAX-1; i++)  
  16.             position |= chess_board[i];  
  17.         position = ~position;   /* 确定最后一个皇后的列位置 */  
  18.         for(i=0; i<QUEEN_MAX-1; i++)  
  19.         {                       /* 最后一个皇后不能和其它在同一斜线 */  
  20.             if((position == chess_board[i]>>(step-i)) ||  
  21.                 (position == chess_board[i]<<(step-i)))  
  22.             {  
  23.                 return;  
  24.             }  
  25.         }  
  26.         solutions++;            /* 解法+1 */  
  27.     }  
  28.     else  
  29.     {  
  30.         for(j=0; j<QUEEN_MAX; j++)  
  31.         {                       /* 每行都有8个位置 */  
  32.             position = 0x1<<j;  
  33.             for(i=0; i<step; i++)  
  34.             {                   /* 当前皇后不能和其它在同一列和同一斜线 */  
  35.                 if(((position & chess_board[i]) != 0) ||  
  36.                     (position == chess_board[i]>>(step-i)) ||  
  37.                     (position == chess_board[i]<<(step-i)))  
  38.                     break;  
  39.             }  
  40.             if(i == step)  
  41.             {                   /* 进行下一步 */  
  42.                 chess_board[i] = position;  
  43.                 Queen8(step+1);  
  44.             }  
  45.         }  
  46.     }  
  47.     return;  
  48. }  
  49.   
  50. int main()  
  51. {  
  52.     Queen8(0);  
  53.     printf(“%d\n”, solutions);  
  54.     return 0;  
  55. }  
    原文作者:八皇后问题
    原文地址: https://blog.csdn.net/marvel_cheng/article/details/45268677
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞