用回溯法解决八皇后问题--C语言

问题描述:要求在8x8的国际象棋棋盘上放入八个皇后,使得任意两个皇后不能处于同一列,同一行,同一条斜线上。
用回溯法解决八皇后问题--C语言_第1张图片
算法思路:
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 
#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; 
		}
	}
}

你可能感兴趣的:(C语言笔记,八皇后,C语言,回溯法)