八皇后
问题陈述:
国际象棋中的皇后可以直线前进,吃掉遇到的所有棋子,如果棋盘上有八个皇后,则这八个皇后如何相安无事的放置在棋盘上?
问题解法:
关于棋盘的问题,都可以用递归求解,然而如何减少递归的次数?在八皇后问题中,不必要检查所有的格子,例如若某列检查过,该列的其它格子就不用检查了,这种方法称为分支修剪。
代码详解:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #define N 8 5 6 using namespace std; 7 8 int column[N+1]; //同行是否有皇后,1表示有 9 int rup[2*N+1]; //右上及左下是否有皇后 x+y = c 10 int lup[2*N+1]; //左上及右下是否有皇后 x-y = c 11 int queen[N+1] = {0}; //皇后纵坐标 12 int num; //解法编号 13 14 void backtrack(int); //递归求解 15 void showAnswer(); 16 17 int main() 18 { 19 int i; 20 num = 0; 21 22 for(i=0; i<=N; i++) { 23 column[i] = 1; 24 } 25 26 for(i=1; i<=2*N; i++) { 27 rup[i] = lup[i] = 1; 28 } 29 30 //从第一列开始遍历 31 backtrack(1); 32 33 return 0; 34 } 35 36 void backtrack(int i) { 37 int j; 38 if(i>N) { 39 showAnswer(); 40 }else { 41 for(j=1; j<=N; j++) { 42 //判断横向 对角线方向是有皇后 43 if(column[j]==1 && rup[i+j]==1 && lup[i-j+N]==1) { 44 queen[i] = j; 45 column[j] = rup[i+j] = lup[i-j+N] = 0; 46 //遍历下一列 47 backtrack(i+1); 48 column[j] = rup[i+j] = lup[i-j+N] = 1; 49 } 50 } 51 } 52 } 53 54 void showAnswer() { 55 int x, y; 56 printf("\nSolve %d\n", ++num); 57 for(y=1; y<=N; y++) { 58 for(x=1; x<=N; x++) { 59 if(queen[y] == x) { 60 printf("Q "); 61 }else { 62 printf("* "); 63 } 64 } 65 printf("\n"); 66 } 67 }
效果图(92种摆法):