近期仔细观看数据结构一书,看到了4皇后问题(8皇后问题的简化),在此进行记录。
问题描述
求4皇后问题的所有合法布局。
要求:
在一个4*4的棋盘上,每个(皇后)棋子有四个选择的位置,但在任何时刻,棋盘的合法布局都必须满足该约束条件:任何两个棋子都不占据棋盘上的同一行、或者同一列、或者同一对角线。
思考
类似的构造一棵树,根为空棋盘,
第一层节点为在棋盘的第一层放置一个棋子,(四种可能,因为棋盘的第一行为4个格)
第二层节点为在第一层摆放一个棋子的前提下,在棋盘的第二层再放置一个节点
……
类似的构造出一颗四叉树。
解法
那么。求所有合法布局的过程就是在上述约束条件下,先根遍历所得的四叉树,然后判断是否满足条件。
遍历过程中的操作为:
1,判断棋盘上是否已经得到一个完整的布局,(即棋盘上是否已经摆放好了4个棋子);
2,若是,输出该布局;
3,若不是,依次先根遍历满足约束条件的各棵子树,即首先判断该子树根的布局是否合法;
4,若合法,则先根遍历该子树;
5,否则,剪去该子树分支。
伪代码实现
void Trial(int i,int n){
//进入本函数时,在n*n的棋盘前(i-1)行,已经放置了满足约束条件的(i-1)个棋子
//现在从第 i 行继续为后续棋子选择合适位置
//当 i>n 时,求得一个合法布局,输出.
if(i > n){
//n为4就是4皇后问题
输出棋盘的当前布局
}
else{
for(j=1;j<=n;++j){
在第 i 行 第 j 列放置一个棋子;
if(当前布局合法){
Trial(i+1,n);
}
移走第 i 行第 j 列的棋子;
}
}
}
该算法可以进一步求精,是回溯法的一般模式,可以解决骑士游历、迷宫问题、选取最优解问题等