[算法]八皇后问题

深度优先算法

深度优先算法(dfs)是搜索算法中的一种,其基本思想为尽可能的找到树的分支,类似于树的先序遍历,是树先序遍历的推广。

这里以具体实例说明。

八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n*,而皇后个数也变成n。当且仅当n = 1或n ≥ 4时问题有解

对于皇后放置在棋盘产生的影响为行,列,所在格斜线*(后文中斜线均指与主,副对角线平行或共线的直线)*内均不能继续放置皇后,我们可以将它们做出标记
那么知道一点坐标,便可以标识该对角线上所有的点。即pdiag[x-y+6],cdiag[x+y]。

每个格子有一一对应的行,列, (列,行),记作(x,y)试规定以左下角格子为(1,1)向右延伸为(1,2), (1,3),向下延伸为(2,1), (3,1)第可以理解为第y行第x列,那么对角线可以表示为主对角线x-y=0(下图绿线),则副对角线为 x+y = 9,

不难看出,平行或共线于主对角线的方程为x-y = a, a属于[-6,6]且为正整数(注意有序数对(1,8), (8,1)不存在这样的对角线),平行或共线于副对角线的方程x +y = b , b属于(2,16) (类似的(1,1), (8,8)不存在这样的对角线)

将与主对角线平行或共线的直线的记作pdiag-a,与副对角线平行或共线的直线记作cdiag-b,自然的我们考虑映射到数组中作为斜线的标记
p d i a g [ a + 6 ] = p d i a g − a , c d i a g [ b ] = c d i a g − b pdiag[a + 6] = pdiag-a, cdiag[b] = cdiag-b pdiag[a+6]=pdiaga,cdiag[b]=cdiagb

还有一点,棋盘为八行八列,放置八皇后,若解,则表明,每列,每行均有皇后,我们考虑放置第x列的皇后,应该放置在行数,若该格点,并未被其他皇后攻击,则放置皇后,并标记各个变量,

#include<stdio.h>
int pdiag[12], cdiag[16], y[9];//如果已被皇后占据,则标记为1即可,y[i]代表第i行是否已存在皇后。
int count;
int queue[9];
void dfs(int x) {
	if (x == 9) {//当x等于九,则表明,第八位皇后已放置
		count++;
		for (int j = 1; j < 9; ++j) {
			printf("(%d,%d)\n", j, queue[j]);
	 }
		printf("over\n");
		return;
	}
	for (int i = 1; i < 9; i++) {
		if (y[i] == 0 && pdiag[x - i + 6] == 0 && cdiag[x + i] == 0) {
			queue[x] = i;//含义为处于第x列的皇后位于第i行。
			y[i] = 1, pdiag[x - i + 6] = 1, cdiag[x + i] = 1;
			dfs(x + 1);
			y[i] = 0, pdiag[x - i + 6] = 0, cdiag[x + i] = 0;//注意,回溯,取消皇后产生的影响。
		}
	}
}
int main() {
	dfs(1);
	printf("%d", count);
	return 0;
}


运行结果如下:

八皇后是一道比较经典的搜索问题,我们可以通过该题了解深度优先算法的基本模型,对于推广至n皇后问题的求解问题,与本题大同小异,这里就不再赘述,读者可以自行尝试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值