问题简述:
一个n*n的棋盘,皇后之间不能处于同一行同一列,也不能处于同一对角线上面
n叉树方案:
显约束:皇后不能处于同一行上面
隐约束(剪枝函数):皇后不能处于同一列,不能处于同一对角线
bool Place(int k){
for(int j = 1;j<k;j++){//对前面k行放的皇后一个个遍历,判断当前位置的合法性
if(abs(k-j)==abs(x[j]-x[k]) || x[k]==x[j]){//是否与第j行的皇后处于同一列或者处于同一对角线
return false;
}
}
return true;
}
void backtrack(int t){//t控制行
if(t>n){ //到达叶子结点,方案数加一
sum++;
}else{
for(int i=1;i<=n;i++){//控制列
if(Place(t)){//剪枝函数:是否满足要求
x[t] = i;//把t行的皇后放在第i列
backtrack(t+1);
}
}
}
}
排列树方案(解空间树更小,效率更高):
显约束:皇后不能处于同一行同一列中(符合排列的特性,故使用排列树)
隐约束(剪枝函数):皇后不能处于同一对角线上面
bool Place(int k){
for(int j = 1;j<k;j++){//对前面k行放的皇后一个个遍历,判断当前位置的合法性
if(abs(k-j)==abs(x[j]-x[k])){//是否与第j行的皇后处于同一对角线
return false;
}
}
return true;
}
void backtrack(int t){//t控制行
if(t>n)sum++;
else{
for(int i=t;i<=n;i++){//控制第t行的排列数 ,x[i]是1到n的排列数
swap(x[t],x[i]);//交换顺序
if(Place(t)){
backtrack(t+1);
}
swap(x[t],x[i]);
}
}
}