八皇后问题,递归法实现

  八皇后问题,是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 }

 

posted @ 2014-12-16 20:55  伟博赵  阅读(1231)  评论(0编辑  收藏  举报