回溯法与N皇后问题

N皇后问题要求求解在N*N的棋盘上放置N个皇后,并使各皇后彼此不受攻击的可能的棋盘布局,皇后彼此不受攻击的所有可能的布局,皇后彼此不受攻击的约束条件是:任何两个皇后均不能在棋盘同一行、同一列或者在对角线上出现。

由于N皇后问题不允许两个皇后在同一行,所以,可用一维数组X表示N皇后问题的解,X[i]表示第i行的皇后所在的列,条件表述如下:

  • X[i] = X[s],则第i行和第s行皇后在同一列上
  • 如果第i行的皇后在第j列,第s行的皇后在第t列,即X[i] = j 和 X[s] = t,则只要i - j = s- t 或者 i + j = s + t,说明两个皇后在对角线上,对两个等式进行变换后,得到结论,只要|i- s| = |j - t|(即|i- s| = |x[i] - x[s]|),则皇后在同一对角线上

解N皇后问题需要遍历解空间树,遍历中要随时判定当前棋盘布局是否满足要求,符合要求则继续向下遍历,直至判断得到一个满足约束条件的叶子结点,从而获得一个满足要求的棋盘布局,不符合要求的结点将被舍弃(称之为剪枝),并回溯到上一层的结点继续遍历,当整棵树遍历结束时,已获得所有满足要求的棋盘布局
回溯法与N皇后问题_第1张图片

上面的就是高度为3的解空间树,树的每一层与棋盘的每一行是对应的,首先选择第一行的皇后的位置的时候,是有三个选择的,而这三个选择都是不发生冲突的,因为此时棋盘上还没有任何皇后,当选择第二行的皇后的位置时,对于以上一次选择的为根的子树而言,只有两种选择,而此时就需要判断是否与之前的选择有冲突,如果有冲突的话就需要剪枝(就是说这种方法不符合要求,不必再继续往下尝试了),按照这种方法直至找到满足题意的结果进行输出。

皇后位置满足约束条件的判定如下:

int place(int s) {
    int i = 1;
    for(; i < s; i++) {
        if(abs(i-s) == abs(X[i]-X[s]) || X[i] == X[s]) {
            return false;
        }
    }

    return true;
} 

回溯算法:

void Trial(int i, int n) {
    int j, k;
    if(i > n) {
        //输出 
        for(k = 1; k <= n; k++) {
            printf("%d ", X[k]);
        }
        printf("\n");
    } else {
        for(j = 1; j <= n; j++) {
            X[i] = j;
            if(place(i)) {
                Trial(i+1, n);
            }
        }
    } 
}

完整代码:

#include
#include
#include

#define true 1
#define false 0

void Trial(int i, int n, int *X);
int place(int s, int *X);

int place(int s, int *X) {
    int i = 1;
    for(; i < s; i++) {
        if(abs(i-s) == abs(X[i]-X[s]) || X[i] == X[s]) {
            return false;
        }
    }

    return true;
} 
void Trial(int i, int n, int *X) {
    int j, k;
    if(i > n) {   //输出 
        for(k = 1; k <= n; k++) {
            printf("%d ", X[k]);
        }
        printf(" \n");
    } else {
        for(j = 1; j <= n; j++) {
            X[i] = j;
            if(place(i, X)) {
                Trial(i+1, n, X);
            }
        }
    } 
}


void main(void) {
    int n;
    int *Queen = NULL;
    printf("请输入皇后的个数.\n");
    scanf("%d", &n);
    Queen = (int *)malloc(sizeof(int) * (n+1));
    Trial(1, n, Queen); 
} 

运行结果:
回溯法与N皇后问题_第2张图片

你可能感兴趣的:(数据结构与算法)