在棋盘上放置8个皇后,使得她们互不攻击,此时每个皇后的攻击范围为同行、同列、同对角线,要求找出所有解,如图所示:
最简单的思路是把问题转换为“从64个格子中选一个子集”,使得“子集中恰好有8个格子”,且任意两个选出的格子都不在同一行,同一列或同一个对角线上。这正是子集枚举问题。然而,64个格子的子集有2^64个,太大了,这并不是一个很好的模型。
第二个想法是把问题转换成“从64个格子中选8个格子”,这是组合生成问题,根据组合数学,有4.426*10^9种方案,仍然不够好。
经过思考,不难发现以下事实:恰好每行每列放置一个皇后,如果用C[x]表示第x行皇后的列编号,则问题变成了全排列生成问题,而我们知道,0-7的排列一共只有8!=40320个,枚举量不会超过它。
下面的程序简洁的求解了八皇后问题。在主程序中读入n,并为tot清零,然后调用search(0),即可得到解的个数tot。
void search(int cur)
{ int i,j;
if (cur == n) tot++; /**递归边界,只要走到了这里,所有的皇后必然不冲突*/
else
for (i=0 ;i<n; i++)
{
int ok=1;
C[cur]=i; /**试把第cur行的皇后放在第i列*/
for (j=0; j<cur ;j++ ) /**检查是否和前面的皇后有冲突*/
if (C[cur]==C[j] || cur-C[cur]==j-C[j] || cur+C[cur]==j+C[j])
{ ok=0 ; break;}
if (ok) search(cur+1);
}
}
注意:既然是逐行放置的,则皇后肯定不会横向攻击,所以只要检查是否纵向或斜向攻击即可。条件cur-C[cur]==j-C[j] || cur+C[cur]==j+C[j]用来判断皇后(cur,C[cur])和(j,C[j])是否在同一条对角线上。