八皇后

//八皇后
//(回溯法(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
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞