回溯法与N皇后问题

来源:互联网 发布:认识奢侈品的软件 编辑:程序博客网 时间:2024/06/05 09:03

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皇后问题需要遍历解空间树,遍历中要随时判定当前棋盘布局是否满足要求,符合要求则继续向下遍历,直至判断得到一个满足约束条件的叶子结点,从而获得一个满足要求的棋盘布局,不符合要求的结点将被舍弃(称之为剪枝),并回溯到上一层的结点继续遍历,当整棵树遍历结束时,已获得所有满足要求的棋盘布局
这里写图片描述

上面的就是高度为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<stdio.h>#include<math.h>#include<malloc.h>#define true 1#define false 0void 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); } 

运行结果:
这里写图片描述

0 0
原创粉丝点击