在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即随意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
结题思想:先给第一列的皇后一位置,依据规则。然后确定第二行皇后位置。以此类推,确定其余每列的皇后的位置。得出问题的解
给棋盘设置一个二维数组chess[8][8],所有初始化为0。找到每一列中合适的位置并赋为1。而确定列中元素的位置没有确定行中元素位置方便。
能够转化为求解每行中这种一个合适位置。找到则进行下一行的寻找,直到行数为8时递归结束获得问题的解。
定义两个函数EightQueen(row,n,chess)用于递归调用下一行的推断、safePosition(row,n,chess)用于需找安全的位置。即元素所在行、列及左右两条对角线上都不能有皇后存在。
代码例如以下:
#include <stdio.h> int count;//全局变量记录有多少种 int safePositon(int row, int n, int (*chess)[8]) { int i,j,flag1=0,flag2=0,flag3=0,flag4=0,flag5=0; //推断列方向 for(i=0; i<8; i++) { if(*(*(chess+i)+n) !=0) { flag1=1; break; } } //推断左上方 for(i=row, j=n; i >= 0 && j >= 0; i--, j--) { if(*(*(chess+i)+j) !=0) { flag2=1; break; } } //推断右下方 for(i=row, j=n; i<8 && j<8; i++, j++) { if(*(*(chess+i)+j) !=0) { flag3=1; break; } } //推断右上方 for(i=row, j=n; i >=0 && j<8; i--, j++) { if(*(*(chess+i)+j) !=0) { flag4=1; break; } } //推断左下方 for(i=row, j=n; i<8 && j >= 0; i++, j--) { if(*(*(chess+i)+j) !=0) { flag5=1; break; } } if(flag1 || flag2 || flag3 || flag4 || flag5) { return 0; } else { return 1; } } void EightQueen(int row, int n, int (*chess)[8]) { //row表示行,j表示列。(*chess)[8]表示指向棋盘每一行的指针;一行一行的递归 int chess2[8][8],i,j; for(i=0; i<n; i++) { for(j=0; j<n; j++) { chess2[i][j]=chess[i][j]; } } if(row == 8)//递归的结束条件 { count++; printf("第%d种 ",count); for(i=0; i<8; i++) { for(j=0; j<8; j++) { printf("%d ",*(*(chess2+i)+j)); } printf(" "); } } else { for(j=0; j<8; j++) { if(safePositon(row, j, chess)) { for(i=0; i<8; i++) *(*(chess2+row)+i)=0; *(*(chess2+row)+j)=1; EightQueen(row+1, n, chess2); } } } } int main(void) { int i,j,chess[8][8]; if(freopen("D:\OUTPUT.txt","w",stdout)==NULL) fprintf(stderr,"errorredirectingstdout "); for(i=0; i<8; i++) { for(j=0; j<8; j++) { chess[i][j]=0;//棋盘的初始化 } } EightQueen(0, 8, chess); printf("一共同拥有%d种 ",count); fclose(stdout); }因为生成结果多。控制台的缓存不足以显示全部结果。
在这里用freopen("D:\OUTPUT.txt","w",stdout)==NULL将stdout重定向到文件里保存。
若要又一次将输出重定向到控制台。能够调用stream=freopen("CON","w",stdout);(stream是一个文件指针)