八皇后 --- 回溯 与 递归

八皇后:在8X8的棋盘上,放置8个皇后,每两个皇后不能同时出现在一个列上或一行上或对角线上;

回溯法: 用栈(数组arr[8])表示8行,arr[i]存放第i行所在的列(1~8), topid表示栈顶位置;
从第1行开始赋值(从1到8尝试),并且检查冲突
第1行赋值成功后,开始给第2行开始赋值(从1到8尝试),并且检查冲突

1、每当前面一行赋值成功,则topid++,重新进入while循环,则开始对下一行赋值;
2、如果当前行分配1-8无法满足条件,则将栈顶arr[topid]归0,回退到上一行,进入while循环,重新对arr[topid-1]进行赋新值(arr[topid-1]++);
3、当进入while循环,topid为8时,说明前面对数组成功分配了值,则将结果打印,并回退到上一行(topid-1),尝试赋新值(arr[topid-1]++);

每当后面的行没有新的赋值策略,则栈顶回退;最终的结果是,第1行(栈顶topid=0)的赋值到了第8列;当尝试9时,失败,栈顶继续回退导致topid=-1,退出while循环

C++ 代码(回溯)

#include 
#include 
#define NUM 8

bool conflict(int arr[NUM],int id, int x)
{
     
	for(int i =0; i < id; i++){
     
		if(arr[i] == x || id-i==abs(arr[i]-x)) {
     
			return true;
		}
	}
	return false;
}
void printqueen(int arr[NUM], int* count) {
     
	for(int i = 0; i< NUM; i++) {
     

		for(int j = 0; j < NUM; j++) {
     
			if(j!=arr[i]-1) printf("* ");
			else printf("%d ", arr[i]);
		}
		printf("\n");
	}
	*count += 1;
	printf("count = %d\n", *count);
}
int main()
{
     
	int arr[NUM] = {
     0};
	int topid = 0;
	int count = 0;
	while(topid>=0) {
     
		if(topid==NUM) {
     
			printqueen(arr, &count);
			topid--;
		}
		int x = arr[topid]+1;
		while(x < NUM+1 && conflict(arr, topid, x)) {
     
			x++;
		}
		if(x<NUM+1) {
     
			arr[topid]=x;
			topid++;
		} else {
     
			arr[topid] = 0;
			topid--;
		}
	}
	system("pause");
	return 0;
}

结果:count = 92种分配方法。

递归法
Python代码(递归) 取自《python基础教程》

#queen.py
def conflict(numx, state):
    for i in range(len(state)):
        if abs(state[i] - numx) in (0, len(state)-i):   #很6的写法
            return True
    return False

def queens(num, state):
    for pos in range(num):
        if not conflict(pos, state):
            if len(state) == num-1:
                yield (pos,)
            else:
                for result in queens(num, state + (pos,)):
                    yield (pos,) + result

>>> list(queen.queens(8, ()))

你可能感兴趣的:(算法,算法,python)