标签:八皇后
在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种\n",count); for(i=0; i<8; i++) { for(j=0; j<8; j++) { printf("%d ",*(*(chess2+i)+j)); } printf("\n"); } } 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\n"); for(i=0; i<8; i++) { for(j=0; j<8; j++) { chess[i][j]=0;//棋盘的初始化 } } EightQueen(0, 8, chess); printf("一共有%d种 \n",count); fclose(stdout); }由于生成结果多,控制台的缓存不足以显示所有结果。在这里用freopen("D:\\OUTPUT.txt","w",stdout)==NULL将stdout重定向到文件中保存。若要重新将输出重定向到控制台,可以调用stream=freopen("CON","w",stdout);(stream是一个文件指针)
标签:八皇后
原文地址:http://blog.csdn.net/codebat/article/details/40187481