八皇后问题、N皇后问题回溯法详解

/* * 回溯法解N皇后问题 * 使用一个一维数组表示皇后的位置 * 其中数组的下标表示皇后所在的行 * 数组元素的值表示皇后所在的列 * 这样设计的棋盘,所有皇后必定不在同一行 * * 假设前n-1行的皇后已经按照规则排列好 * 那么可以使用回溯法逐个试出第n行皇后的合法位置 * 所有皇后的初始位置都是第0列 * 那么逐个尝试就是从0试到N-1 * 如果达到N,仍未找到合法位置 * 那么就置当前行的皇后的位置为初始位置0 * 然后回退一行,且该行的皇后的位置加1,继续尝试 * 如果目前处于第0行,还要再回退,说明此问题已再无解 * * 如果当前行的皇后的位置还是在0到N-1的合法范围内 * 那么首先要判断该行的皇后是否与前几行的皇后互相冲突 * 如果冲突,该行的皇后的位置加1,继续尝试 * 如果不冲突,判断下一行的皇后 * 如果已经是最后一行,说明已经找到一个解,输出这个解 * 然后最后一行的皇后的位置加1,继续尝试下一个解 */ #define MAX_LENGTH 1024 /* * 检查第n行的皇后与前n-1行的皇后是否有冲突 * 发生冲突的充分必要条件是: * a) 两皇后处于同一列,即a[i] == a[n] * b) 两皇后处于同一斜线,即|a[i] - a[n]| == |i - n| == n - i */ int is_conflict(int *a, int n) { int flag = 0; int i; for ( i = 0; i < n; i++ ) { if ( a[i] == a[n] || a[i] - a[n] == n - i || a[n] - a[i] == n - i ) { flag = 1; break; } } return flag; } /* * 输出皇后的排列 */ void print_board(int *a, int n) { int i, j; for ( i = 0; i < n; i++ ) { for ( j = 0; j < a[i]; j++ ) { printf(" "); } printf("Q"); for ( j = a[i] + 1; j < n; j++ ) { printf(" "); } printf("\n"); } printf("--------\n"); } /* * 初始化棋盘,所有皇后都在第0列 */ void init_board(int *a, int n) { int i; for ( i = 0; i < n; i++ ) { a[i] = 0; } } /* * 解决N皇后问题 */ int queen(int n) { int count = 0; int a[MAX_LENGTH]; init_board(a, n); int i = 0; while ( 1 ) { if ( a[i] < n ) { // 如果皇后的位置尚未超出棋盘范围 // 需要检查第i行的皇后是否与前i-1行的皇后冲突 if ( is_conflict(a, i) ) { // 如果冲突,尝试下一个位置 a[i]++; continue; } if ( i >= n - 1 ) { // 如果已经到最后一行,也即找到一个解,首先输出它 count++; print_board(a, n); // 然后尝试当前行的皇后的下一个位置 a[n-1]++; continue; } // 没有冲突,尝试下一行 i++; continue; } else { // 皇后的位置已经超出棋盘范围 // 那么该行的皇后复位 a[i] = 0; // 回退到上一行 i--; if ( i < 0 ) { // 已经不能再退了,函数结束 return count; } // 尝试上一行的皇后的下个位置 a[i]++; continue; } } } int main(void) { int n = 8; int count = queen(n); printf("%d solutions in %d queens problem\n", count, n); return 0; }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值