八皇后问题,递归法实现

  八皇后问题,是19世纪著名的数学家高斯在1850年提出的:在8×8格的国际象棋盘上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列、同一斜线上,试问有多少种摆法?高斯先生给出的答案是“76”种,实际是76种吗?

  八皇后问题是回溯算法的典型应用,但是本文提供递归的求法。

  递归的核心思想可以总结成:把一个复杂的问题无限缩小,每个小问题的解法都是一样的,最终归结于求解每个小问题的原型。递归编程的思路可以假设所有的问题都已解决,来到结束条件,这是非常简单的,然后再调用自身求解整个问题。虽然递归的效率比较低,但是可以大大降低思考的程度。

  八皇后问题的递归思路为:先放置第一个皇后;把第一个皇后所能攻击到的区域排除,放置第二个皇后;把第二个皇后所能攻击到的区域排除,放置第三个皇后......直至放置第八个皇后,第八个皇后所能放置的区域只有一个格子。

八皇后问题,递归法实现

 

  1 //八皇后问题,递归法实现

  2 #include <stdio.h>

  3 

  4 int count = 0;

  5 

  6 //判断第row行j列是否安全,判断列、左上、右上、左下、右下

  7 int Safe( int row, int j, int (*chess)[8])

  8 {

  9     int i, k, flag1=0, flag2=0, flag3=0, flag4=0, flag5=0;

 10 

 11     //判断列方向是否安全

 12     for( i=0; i<8; i++)

 13     {

 14         if(*(*(chess+i)+j) !=0)

 15         {

 16             flag1 = 1; //不安全

 17             break;

 18         }

 19     }

 20 

 21     //判断左上方是否安全

 22     for( i=row, k=j; i>=0 && k>=0; i--,k--)

 23     {

 24         if(*(*(chess+i)+k) !=0)

 25         {

 26             flag2 = 1; //不安全

 27             break;

 28         }

 29     }

 30 

 31     //判断右下方是否安全

 32     for( i=row, k=j; i<8 && k<8; i++,k++)

 33     {

 34         if(*(*(chess+i)+k) !=0)

 35         {

 36             flag3 = 1; //不安全

 37             break;

 38         }

 39     }

 40 

 41     //判断右上方是否安全

 42     for( i=row, k=j; i>=0 && k<8; i--,k++)

 43     {

 44         if(*(*(chess+i)+k) !=0)

 45         {

 46             flag4 = 1; //不安全

 47             break;

 48         }

 49     }

 50 

 51     //判断左下方是否安全

 52     for( i=row, k=j; i<8 && k>=0; i++,k--)

 53     {

 54         if(*(*(chess+i)+k) !=0)

 55         {

 56             flag5 = 1; //不安全

 57             break;

 58         }

 59     }

 60 

 61     if( flag1 || flag2 || flag3 || flag4 || flag5)

 62         return 0;

 63     else

 64         return 1;

 65 }

 66 

 67 // row :起始行

 68 //  n  :列数

 69 // (*chess)[8] :指向棋盘每一行的指针

 70 void EightQueen( int row, int n, int (*chess)[8])

 71 {

 72     int i, j, chessTemp[8][8];    //用于存放当前形式的棋盘

 73 

 74     for( i=0; i<8; i++)

 75     {

 76         for( j=0; j<8; j++)

 77         {

 78             chessTemp[i][j] = chess[i][j];

 79         }

 80     }

 81 

 82     if( 8==row )    //递归终止条件,即假设已经找到一种棋盘分布,将它打印

 83     {

 84         printf("第 %d 种棋盘:\n",count+1);

 85         for( i=0; i<8; i++)

 86         {

 87             for( j=0; j<8; j++)

 88             {

 89                 printf("%d ",*(*(chessTemp+i)+j));

 90             }

 91             printf("\n");

 92         }

 93         printf("\n");

 94         count++;

 95     }

 96     else    //进入递归

 97     {

 98         for( j=0; j<n; j++) //对第row行的各列扫描

 99         {

100             if( Safe( row, j, chess))   //如果第row行,j列安全

101             {

102                 for( i=0; i<8; i++)

103                 {

104                     *(*(chessTemp+row)+i) = 0;  //第row行赋0

105                 }

106                 *(*(chessTemp+row)+j) = 1;      //第row行,j列赋1

107 

108                 EightQueen( row+1, n, chessTemp);

109             }

110         }

111     }

112 }

113 

114 int main()

115 {

116     int chess[8][8], i, j;

117 

118     for( i=0; i<8; i++)

119     {

120         for( j=0; j<8; j++)

121         {

122             chess[i][j] = 0;

123         }

124     }

125 

126     EightQueen(0, 8, chess); //第0行开始,共有8列

127     printf("共有 %d 种方法:",count);

128 

129     return 0;

130 }

 

你可能感兴趣的:(八皇后)