20150410 递归实现八皇后问题
2015-04-10 Lover雪儿
十九世纪著名的数学家高斯1850年提出:
在8x8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意的连个皇后都不能处于同一行、同一列或者统一斜线,问有多少种摆法。
以下是其中一种解法,如图所示:
当年高斯先生没日没夜的计算,得出结论是76种。
其实正确的结论是92中,此处我们就来编程计算一下正确的答案。
1 //八皇后问题 2 #include <stdio.h> 3 4 static int count = 0; //算法的总数 5 6 //判断第row行第col列位置是否有危险,是否在其他皇后的攻击范围 7 //没有危险,则返回真 8 int NotDanger(int row, int col, int (*chess)[8]){ 9 int i, k; 10 int flag_1=0, flag_2=0, flag_3=0, flag_4=0, flag_5=0; 11 //判断列的方向有没有危险 标志位flag_1 12 for( i=0; i<8; i++) 13 { 14 if( *(*(chess + i)+ col) != 0) //判断是否有棋子 15 { 16 flag_1 = 1; 17 break; 18 } 19 } 20 //判断左上方有没有危险 标志位flag_2 21 for(i = row, k = col; i>=0 && k>=0; i--, k--) 22 { 23 if(*(*(chess + i)+k) != 0) 24 { 25 flag_2 = 1; 26 break; 27 } 28 } 29 //判断右下方有没有危险 标志位flag_3 30 for(i = row, k = col; i<8 && k<8; i++, k++) 31 { 32 if(*(*(chess + i)+k) != 0) 33 { 34 flag_3 = 1; 35 break; 36 } 37 } 38 //判断右上方有没有危险 标志位flag_4 39 for(i = row, k = col; i>=0 && k<8; i--, k++) 40 { 41 if(*(*(chess + i)+k) != 0) 42 { 43 flag_4 = 1; 44 break; 45 } 46 } 47 //判断左下方有没有危险 标志位flag_5 48 for(i = row, k = col; i<8 && k>=0; i++, k--) 49 { 50 if(*(*(chess + i)+k) != 0) 51 { 52 flag_5 = 1; 53 break; 54 } 55 } 56 if( flag_1 || flag_2 || flag_3 || flag_4 || flag_5){ 57 return 0; 58 }else{ 59 return 1; 60 } 61 } 62 63 //八皇后算法 row:起始行 col:列数 *chess[8]:指向棋盘每一行的指针 64 void EightQueen(int row, int col, int (*chess)[8]) 65 { 66 int chess_tmp[8][8], i, j; 67 for(i = 0; i<8; i++){ 68 for(j = 0; j<8; j++){ 69 chess_tmp[i][j] = chess[i][j]; 70 } 71 } 72 //当指针走到了第八行时,说明已经计算好,打印出棋盘 73 if( 8 == row){ 74 printf("第 %d 种方法:\n",count+1); 75 for(i = 0; i<8; i++){ 76 for(j = 0; j<8; j++){ 77 printf("%d ",*(*(chess_tmp+i)+j)); 78 } 79 printf("\n"); 80 } 81 printf("\n\n"); 82 count++; 83 }else{ 84 //判断这个位置是否有危险,是否在其他皇后的攻击范围 85 //如果没有危险,继续往下判断,知道row = 8 86 for( j=0; j<col; j++){ 87 if(NotDanger(row, j, chess_tmp)){ //判断是否危险 88 for(i = 0; i<8; i++){ //将整行所有的列赋值为0 89 *(*(chess_tmp + row)+i) = 0; 90 } 91 *(*(chess_tmp + row)+j) = 1; 92 EightQueen(row+1, col, chess_tmp); //递归调用 93 } 94 } 95 } 96 } 97 98 int main(void) 99 { 100 int chess[8][8], i, j; 101 102 //初始化八皇后的棋盘,1:放置皇后 0:没有皇后 103 for(i = 0; i<8 ; i++){ 104 for(j = 0; j<8 ; j++){ 105 chess[i][j] = 0; 106 } 107 } 108 109 freopen("EightQueen.txt", "w", stdout); //重定向输出到out.txt文件中 110 111 EightQueen(0 , 8, chess); 112 printf("总共有 %d 种解决方法\n\n",count); 113 114 return 0; 115 }
运行成功后在当前文件夹生成一个文件EightQueen.txt,内容如下所示: