问题描述:要求在8x8的国际象棋棋盘上放入八个皇后,使得任意两个皇后不能处于同一列,同一行,同一条斜线上。
算法思路:
1) 判断皇后之间有没有冲突,要引入四个量–row(行号,也对应于皇后的编号),column[ ](列号),slash[ ](斜线方向), bslash[ ](反斜线方向);
2) 由棋盘的布局可以发现,在斜线方向上有15条对角线,每一条穿过的各个方格有如下性质:该方格的行号加列号等于一个常量。15条对角线分别对应:0,1,2,…,14;而15条反斜线方向的对角线,每一条穿过的各个方格的行号与列号之差也是一个常量,分别对应于:-7,-6,…,6,7。由这些特征可以确定每一条对角线。程序中:slash[row + col] = 1 ,表示 第row行,第col列的方格所对应的斜线没有冲突;bslash[row + col + 7] = 1 ,表示 第row行,第col列的方格所对应的反斜线没有冲突(加7是因为数组是要从0开始的)。然后数组column[ ]表示列方向的情况, column[ i ] = 1,表示第 i 列无冲突,可放置皇后。所以,最终判断判断“column[h]&&slash[row+h]&&bslash[row-h+7]”是否为真;
3)然后从(0,0)开始放0号皇后,要令column[0] = 0,slash[0] = 0,bslash[7] = 0,表示这些方向都不能放皇后了。之后放1号皇后,例如放置在(1,j)上,它应与0号皇后不发生冲突,同样要标出column[j] = 0,slash[1+j] = 0,bslash[1-j+7] = 0,依次类推,放后面的皇后。直到遇到某个皇后无法在任意一个位置上摆放,那么就要“回溯”–改变前一个皇后的位置,再试自己能不能摆放,如果还不行,就再往回退,重新改变更前面的皇后的位置。
4)如果8个皇后都摆好了,就得到了一次成功的局。接着回退一步,试探第6号皇后还有没有其他位置可放,如果有,再接着试探第7号皇后的摆放位置。这样反复试探,直到找出所有解。
程序运行后会显示所以的摆放方法,一共有92种。
#include <stdio.h>
#define COSZ 8
#define SLSZ 15
#define BSSZ 15
#define QUSZ 8
#define TRUE 1
#define FALSE 0
int column[COSZ], slash[SLSZ], bslash[BSSZ];
int queen[QUSZ];
int row = 0, sum = 0;
void generate(void);
main(){
int c,s;
for(c = 0; c <= 7; ++c){
column[c] = TRUE;
}
for(s = 0; s <= 14; ++s){
slash[s] = TRUE;
bslash[s] = TRUE;
}
printf("rownum:\t0\t1\t2\t3\t4\t5\t6\t7\n\n");
generate();
printf("total:%d\n",sum);
return 0;
}
void generate(void){
int h, i;
for(h = 0; h <= 7; h++){
if(column[h]&&slash[row+h]&&bslash[row-h+7]){
queen[row] = h;
column[h] = FALSE;
slash[row+h] = FALSE;
bslash[row-h+7] = FALSE;
++row;
if(row == 8){
++sum;
printf("%2d",sum);
for(i = 0; i <= 7; i++)
printf("%8d",queen[i]);
printf("\n");
}
else generate();
row--;
slash[row+h] = TRUE;
bslash[row-h+7] = TRUE;
column[h] = TRUE;
}
}
}