引言:在棋盘上放置八个皇后,使得他们互相不攻击,攻击范围为同行同列,同对角线。
解决:
逐行放置,检查当前皇后所放的列,是否和已放皇后的列和对角线有冲突。
检查条件,cur-C[cur]==j-C[j] || cur+C[cur]==j+C[j],用来判断皇后(cur,C[cur])和(j,C[j])是否在同一条对角线上。
原理图:
(a)格子(x,y)的y-x值标识了主对角线 (b)格子(x,y)的x+y值标识了副对角线
void searchs(int cur)
{
int i,j;
if(cur==n) tot++;///计算有多种可能的结果
else for(int i=0;i<n;i++)
{
int ok=1;
C[cur]=i;
for(int j=0;j<cur;j++){ ///检查前cur-1行是否已第cur行有无冲突
if(C[cur]==C[j]||cur-C[cur]==j-C[j]||cur+C[cur]==j+C[j]){
ok=0;break;
}
}
if(ok) searchs(cur+1); ///递归下一行
}
}
除了上述的判断外,还可以利用二维数组vis[2][ ]直接判断当前尝试的皇后所在的列和两个对角线是否已有其他皇后。
注意到主对角线标识y-x可能为负,存取时可加上n。
代码:
void searchs(int cur)
{
int i,j;
if(cur==n) tot++;
else for(int i=0;i<n;i++)
{
if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n])
{
C[cur]=i;
vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1;
searchs(cur+1);
vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0;
}
}
}