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

问题描述:要求在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; 
		}
	}
}
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
八皇后问题是一个经典的回溯算法问题,在C语言中可以通过递归实现。以下是一个简单的示例代码: ```c #include <stdio.h> #define N 8 int board[N][N]; // 检查当前位置是否可以放置皇后 int isSafe(int row, int col) { int i, j; // 检查当前列是否有其他皇后 for (i = 0; i < row; i++) { if (board[i][col] == 1) { return 0; } } // 检查左上方对角线是否有其他皇后 for (i = row, j = col; i >= 0 && j >= 0; i--, j--) { if (board[i][j] == 1) { return 0; } } // 检查右上方对角线是否有其他皇后 for (i = row, j = col; i >= 0 && j < N; i--, j++) { if (board[i][j] == 1) { return 0; } } return 1; } // 解决八皇后问题的递归函数 int solveNQueens(int row) { int col; // 所有行都已经放置好皇后,打印结果 if (row == N) { printf("解决方案:\n"); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { printf("%d ", board[i][j]); } printf("\n"); } printf("\n"); return 1; } // 尝试放置皇后在当前行的每一列 for (col = 0; col < N; col++) { if (isSafe(row, col)) { // 放置皇后 board[row][col] = 1; // 递归处理下一行 solveNQueens(row + 1); // 回溯,撤销当前位置的皇后 board[row][col] = 0; } } return 0; } int main() { // 初始化棋盘 for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { board[i][j] = 0; } } solveNQueens(0); return 0; } ``` 这个代码会输出所有可能的八皇后问题解决方案。每个解决方案都会以矩阵形式打印出来,其中1代表皇后的位置,0代表空格。你可以根据需要对代码进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值