在8 * 8的棋盘上,摆放8个皇后,使其任意两个皇后都不能处于同一行、同一列或同一斜线上,问共有多少种摆法,并且用程序输出这些摆法。
八皇后作为回溯法的经典例题还是值得一做的,这道题基本可以分成以下步骤:
1.初始化棋盘,0代表没有皇后,1代表有皇后。
2.剪枝函数(判断同一行、同一列或同一斜线上是否有皇后)
3.回溯主程序
4.打印棋盘
程序如下:
1 #include "stdafx.h" 2 #include <stdlib.h> 3 const int Max = 8; 4 const int chessMen = 1; 5 int count = 0; 6 //初始化棋盘 7 int chessboard[Max][Max] = {0}; 8 //打印棋盘 9 void Print() 10 { 11 for(int i = 0;i< Max;i++) 12 { 13 for(int j = 0; j < Max;j++) 14 { 15 printf("%d",chessboard[i][j]); 16 if(j == 7) 17 { 18 printf(" "); 19 } 20 } 21 } 22 } 23 //剪枝函数 24 int Cut(int r,int c) 25 { 26 //判断同列不同行的格子里有没有皇后 27 for(int i = 0; i < Max; i++) 28 if(chessboard[i][c] == chessMen) 29 return 0; 30 //判断同行不同列的格子里有没有皇后 31 for(int j = 0; j < Max; j++) 32 if(chessboard[r][j] == chessMen) 33 return 0; 34 //判断右下角斜线位置有没有皇后 35 for(int i = r + 1,j = c + 1;i < Max&&j < Max;i++,j++) 36 if(chessboard[i][j] == chessMen) 37 return 0; 38 //判断左下角斜线位置有没有皇后 39 for(int i = r + 1,j = c - 1;i < Max&&j >= 0;i++,j--) 40 if(chessboard[i][j] == chessMen) 41 return 0; 42 return 1; 43 } 44 //回溯主程序 45 void BackTrack(int num,int queen) 46 { 47 if(num <=0 ||queen == Max) 48 { 49 if(queen == Max) 50 { 51 Print(); 52 count++; 53 printf(" "); 54 } 55 } 56 else 57 { 58 int r = num / Max; 59 int c = num % Max; 60 //核心中的核心 61 if(Cut(r,c)) 62 { 63 chessboard[r][c] = chessMen; 64 BackTrack(num - 1,queen + 1); 65 chessboard[r][c] = 0; 66 } 67 BackTrack(num - 1,queen); 68 } 69 } 70 int _tmain(int argc, _TCHAR* argv[]) 71 { 72 73 BackTrack(Max * Max - 1,0); 74 printf("在%d * %d的棋盘中,%d皇后共有%d中摆法",Max,Max,Max,count); 75 system("Pause"); 76 return 0; 77 }
最后回溯计算出只有88种,但是据说图论有92种。。这个我是没有找到还能优化的地方了...