经典算法问题-01-八皇后

#八皇后问题
###问题描述:
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
###简化问题:
由于八皇后问题的正确答案为92种排列方案,由于正确的棋子放置方式实在太多,难以一一列举,所以先简化问题,解决四皇后的排列,即将8×8棋局改为4×4棋局,规则不变
###建立模型:
要使用C++解决这个问题,首先要建立模型,让问题能够使用数学和C++的控制语句来解决。
将棋盘模拟为一个坐标轴,使用一个数组index将每个棋子定位到坐标轴中,index数组的下标为横坐标值,index[i]的值为纵坐标值,如下图所示,index[0] = 1 ; index[1] = 4 ; index[2] = 2 ; index[3] = 3

经典算法问题-01-八皇后_第1张图片
#方案1----枚举法:
将所有可能的棋子放置情况全部列举出来,一一判断是否合乎条件
###C++程序:

#include
using namespace std;

//判断棋子放置方式是否正确
bool Judge(int *index) {
	for (int i = 0; i < 4; i++){
		for (int j = i + 1 ; j < 4; j++) {
			//判断棋子是否在同一行,或某一对角线上
			//1,横坐标不同		i与j不相等
			//2,纵坐标不同		index[i]与index[j]不相等
			//3,不在同一对角线	index[i]- index[j]的绝对值和j-i的绝对值不相等
			if (index[i] == index[j] || abs(index[i]- index[j])==j-i){
				return false;
			}
		}
	}
	return true;
}

//打印正确的棋子放置方式
void Sloution(int *index) {
	cout << "四皇后问题的一种正确解法,横坐标从0到4的4列上,纵坐标的值依次是:";
	for (int i = 0; i < 4; i++){
		cout << index[i];
	}
	cout << endl;
}

int main() {
	int index[8];
	//多层循环,穷举每一种放置方式
	for (index[0] = 1; index[0] <= 4 ; index[0]++){
		for (index[1] = 1; index[1] <= 4; index[1]++) {
			for (index[2] = 1; index[2] <= 4; index[2]++) {
				for (index[3] = 1; index[3] <= 4; index[3]++) {
					//判断棋子放置是否合乎规则,正确则打印,不正确则继续
					if (Judge(index)){
						Sloution(index);
					}
					else {
						continue;
					}
				}
			}
		}
	}

	cin.get();
	return 0;
 }

上述程序使用了4个for循环来模拟所有可能出现的棋子放置情况,Judge()方法用来判断是否合乎条件

###运行结果:

经典算法问题-01-八皇后_第2张图片

###正确结果的演示:
纵坐标:2413

经典算法问题-01-八皇后_第3张图片

纵坐标:3142

经典算法问题-01-八皇后_第4张图片

##枚举法的优化:
枚举法解决此四皇后问题需要的循环次数太多,四皇后需要4X4X4X4次遍历,才能将所有可能的情况列举出来,八皇后更是要8X8X8X8X8X8X8X8次遍历
枚举法可以进行优化,即若在放置第2,或3个棋子,即没有将棋子全部放入棋盘中时,进行判断,将不符合要求的情况直接排除,不再继续循环,这样能够大大减少循环次数,不必模拟所有棋子放置方式
优化方式:在main方法中做优化,增加判断语句

int main() {
	int index[8];
	//多层循环,穷举每一种放置方式
	for (index[0] = 1; index[0] <= 4; index[0]++) {
		for (index[1] = 1; index[1] <= 4; index[1]++) {
			//增加判断
			if(Judge(index, 2))
				for (index[2] = 1; index[2] <= 4; index[2]++) {
					//增加判断
					if (Judge(index, 3))
						for (index[3] = 1; index[3] <= 4; index[3]++) {
							//判断棋子放置是否合乎规则,正确则打印,不正确则继续
							if (Judge(index, 4)) {
								Sloution(index);
							}
							else {
								continue;
							}
						}
				}
		}
	}

	cin.get();
	return 0;
}

#方案2----回溯法:
main函数:


int main() {

	int index[4] = { 0 };
	int i = 0;
	while (i > -1) {
		index[i]++;
		while (index[i] < 6 && _judge(index, i)) {
			index[i]++;
		}

			if (index[i] <= 4) {

				if (i == 3) {
					//是四皇后的正确结果,调用函数打印正确答案
					result(index);
				}
				else {
					i++;
					index[i] = 0;
				}
			}
			else {
				i--;
			}

	}

	cin.get();
	return 0;
}

_judge函数:

inline bool _judge(int *index, int num) {

	for (int i = 0; i < num; i++) {
		if (index[i] == index[num] || abs(index[i] - index[num]) == num - i) {
			return true;
		}
	}
	return false;

}

result函数:

inline void result(int *index) {
	cout << "四皇后问题的一种正确解法,横坐标从0到4的4列上,纵坐标的值依次是:";
	for (int i = 0; i < 4; i++) {
		cout << index[i];
	}
	cout << endl;
}

经典算法问题-01-八皇后_第5张图片
##使用递归优化程序:
上述程序太难懂,可以使用递归优化上述程序,如下:
result函数和_judge函数不变
回调函数:

void callback(int *index,int i) {
	if (i > 3){
		result(index);
	}
	else{
		int j = 0;
		while (++j <= 4) {
			index[i] = j;
			if (_judge(index, i) == 0) {
				callback(index,i+1);
			}
		}

	}
}

main函数:

int main() {
	int index[4] = { 0,0,0,0 };
	int i = 0;
	callback(index,i);
	cin.get();
	return 0;
}

#方案3----回溯法结合递归和栈数据结构
在严蔚敏编著的C语言数据结构栈数据结构部分,书中提及使用栈解决四皇后问题

经典算法问题-01-八皇后_第6张图片

栈数据结构解决和回溯相关的问题时非常的方便易懂,下面介绍一下使用栈解决四皇后问题,这是本文最简单易懂的方法,但是需要实现编写栈数据结构,当然也可以使用STL中的栈

#include "assist.h"
#include"Stack.h"
#include
//创建一个全局栈
Stack stack(11);
//回调函数
void callback() {
	if (stack.getSize() == 3) {
		cout << "正确答案" << endl;
		stack.Print();
	}
	else {
		int j = 0;
		while (++j <= 4)
		{
			//进栈
			stack.Push(j);
			if (_judge(	stack.getElements(), stack.getSize()) == 0) {
				//打印整个栈中的数据
				stack.Print();
				cout << stack.getSize() << endl;
				callback();
			}
			//弹栈
			stack.Pop();
		}

	}
}


int main() {

	callback();

	cin.get();
	return 0;
}

经典算法问题-01-八皇后_第7张图片

你可能感兴趣的:(算法/数据结构,数据结构与算法基础)