//八皇后
//(回溯法(backtracking))(回溯:将问题分为若干个步骤递归求解,如果当前步骤没有合法的选择,递归函数将不再递归的调用塔本身,而是返回上一层,这样的现象称为回溯(回溯法也常称为递归枚举算法),这类算法的工作原理可以用解答树来描述。
/******/
//关于解答树
//如果某个问题的解可以由多个步骤得到,而每个步骤都有若干个选择(这些候选的方案可能会依赖于先前做出的选择),且可以用递归枚举实现,
//这些算法工作方式就可以使用解答树来描述
#include "stdio.h"
#include "string.h"
#define MAX_LENGTH 12
int position[MAX_LENGTH];//position[i]表示第i行皇后的列编号
int tot = 0;
int tot2 = 0;
void search (int cur,int n) {
if (cur >= n) {
int i;
tot = tot + 1;
for (i = 0;i < n;i++) {
printf ("%d ",position[i]);
}
printf ("\n");
}else {
int i;
int j;
int k;
for (i = 0;i < n;i++) {
int ok = 1;
//列
for (j = 0;j < cur;j++) {
if (position[j] == i) {
ok = 0;
break;
}
}
//正斜角
k = cur-1;
j = i-1;
while (k >= 0 && j >= 0) {
if (position[k] == j) {
ok = 0;
break;
}
k--;
j--;
}
//反斜角
k = cur-1;
j = i+1;
while (k >=0 && j < n) {
if (position[k] == j) {
ok = 0;
break;
}
k--;
j++;
}
if (ok) {
position[cur] = i;
search (cur+1,n);
}
}
}
}
//格子(x,y)的y-x标识了主对角线,而格子(x,y)的x+y标识了副对角线,利用这个小技巧来改写上面的search(int,int)
/** index 0 1 2
* 0 0 1 2
* 1 -1 0 1
* 2 -2 -1 0
* (x,y)的y-x标识了主对角线
*
* index 0 1 2
* 0 0 1 2
* 1 1 2 3
* 2 2 3 4
* (x,y)的y+x标识了副对角线
*/
void search2 (int cur,int n) {
if (cur >= n) {
int i;
for (i = 0;i < n;i++) {
printf ("%d ",position[i]);
}
tot2++;
printf ("\n");
}else {
int i;
int j;
for (i = 0;i < n;i++) {
int ok = 1;
for (j = 0;j < cur;j++) {
if (position[j] == i || position[j] + j == cur + i || position[j] - j == i - cur) {
ok = 0;
break;
}
}
if (ok) {
position[cur] = i;
search2 (cur+1,n);
}
}
}
}
//利用visited[3][2*n]范围标志数组可以直接的判断列和二个对角线是否有其它皇后
//在回溯法中如果使用了辅助的全局的变量,则一定要及时的把它们恢复原来的状态
int visited[3][2 * MAX_LENGTH];
int tot3 = 0;
void search3 (int cur,int n) {
if (cur >= n) {
int i;
tot3++;
for (i = 0;i < n;i++) {
printf ("%d ",position[i]);
}
printf ("\n");
}else {
int i;
for (i = 0;i < n;i++) {
if (0 == visited[0][i] && 0 == visited[1][i - cur + n] && 0 == visited[2][i + cur]) {
position[cur] = i;
visited[0][i] = visited[1][i - cur + n] = visited[2][i + cur] = 1;//因为表示主对角线的y-x可能为负的,可以加个n
search3 (cur+1,n);
visited[0][i] = visited[1][i - cur + n] = visited[2][i + cur] = 0;
}
}
}
}
int main () {
int n;
scanf ("%d",&n);
search (0,n);
printf ("tot = %d\n",tot);
printf ("---------\n");
search2 (0,n);
printf ("tot2 = %d\n",tot2);
printf ("----------\n");
memset (visited,0,sizeof(visited));
search3 (0,n);
printf ("tot3 = %d\n",tot3);
return 0;
}
//input :n = 4
//output:
//1 3 0 2
//2 0 3 1
//tot = 2
//-------
//1 3 0 2
//2 0 3 1
//tot2 = 2
//-------
//1 3 0 2
//2 0 3 1
//tot3 = 2
八皇后
原文作者:八皇后问题
原文地址: https://blog.csdn.net/xiao_niu_1/article/details/9165523
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/xiao_niu_1/article/details/9165523
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。