详细注解八皇后问题

网上八皇后问题的代码一大把,可是“回朔递归”还是理解的不好!

这里是我一步步写出的代码和详细的注释,解释了这个问题的解决用到的“回朔和递归”体现在哪里和怎么体现的两个问题,相信看了之后,对这个问题的解决原理会有深刻的理解的。


如下:

#include <iostream>
#include <stdlib.h>
using namespace std;

#define QUEUE 8  //定义皇后的个数

int queues[QUEUE];//表示一个QUEUE*QUEUE的棋盘,其值queues[i] = 第i个皇后的放置位置,初始值为-1,程序中略去了初始化
		

static int sum = 0;//记录解的个数

bool canPlace(int k, int i)
/*
*用来判定第k个皇后能不能放置在第k行的i位置上。
*因为每行只能放置一个皇后是肯定的事情,所以8个皇后必然是每行放置一个,而我们放置皇后的时候是第i个放置在第k行的。这样给出两个参数即皇后编号k和欲放置位置即可
*k既代码行号,又代表皇后的编号
*/
{
	for( int j = 0; j < k; j++)
	/*
	*这个循环的范围是[0,k)而不是[0,QUEUE)
	*因为对于canPlace函数来说,它的任务是判定第k个皇后能不能放置在第k行的第i列即可以类,此时[k+1,QUUE)都还没有放置皇后
	*因此没有必要对其进行判定。
	*很显然对于这样的判定任务使用循环是正常的策略
	*/
	{
		if( abs(queues[j]-i) == abs(k-j) || queues[j] == i)
		/*
		*abs(queues[j]-i) == abs(k-j)是判定第k个皇后放置在第k行的第j列时,其对角线上有没有已经放置皇后。
		*queues[j] == i是判定第k个皇后放置在第k行的第j列时,该行有没有放置皇后。
		*/
			return false;
	}
	return true;
}
void printSolution()
{
	cout << sum << " solution is: " << endl;
	for( int i = 0; i < QUEUE; i++)
		cout << "queues[" << i << "] = " << queues[i] << endl;
	
}
void queueSolution(int k)
{
/*
*这里传入了一个参数,前面有说k的含义,既代表行号,又代表皇后的编号。
*使用该函数时,传入参数k=0,表示第一个皇后放置在第一行
*这是我们开始解八皇后问题的起点,即在第一行试着放置第一个皇后。
*这个函数的任务是一个放置好一个皇后,然后递归
 */
	for( int j = 0; j < QUEUE; j++)
	/*
	*这个循环是“体现和实现回朔的关键”。用来判定欲放置在第行的第k个皇后能不能放置在第k行的第j列。
	*传入参数是k,k既代表行号,又代表皇后的编号。就表示尝试第k行能不能放置第k个皇后,如果成功放置,再去放置第k+1个皇后
	*而这个循环则是对列的遍历,即尝试应该放置在第k行的第k个皇后能不能放置在这行的第i列上。通过这个循环就可以得到所有的i值
	*而当第k行的第k个皇后顺利(暂时顺利)放置在第i列(第一个i值)时,else	queueSolution(k+1);代码引发递归调用,此时
	*for循环暂停,转而程序跳转到递归的queueSolution函数又进行这个过程。
	*现在假设这个过程执行完毕,那么应该回到这个循环继续执行,即继续寻找适合的i值。当嵌套调用顺利的结束递归时,那么就表示已经找到了一个解决方案
	*此时for循环的继续运行是继续寻找另一个解决方案;当嵌套调用没有顺利结束递归时,那么就表示这个暂时顺利的i值是无效的,此时这个for循环的继续运行
	*是继续寻找正确的解决方案。这里我用了“继续”两个字描述为第k行的第k个皇后寻找适合的i位置的过程,这“回朔”的体现:嵌套以暂停循环进而深入执行,然后又返回朔到循环继续执行
	*/
	{
		if (true == canPlace(k,j))
		{
			queues[k] = j;
			if(k == QUEUE-1)//皇后全部放置好了,此时找到了一个解决方法
			{
				sum++;
				printSolution();
				cout << endl;
			}
			else	queueSolution(k+1);//递归,不管递归是否成功,都会回朔到for循环继续执行,所以这个函数可以将所有的解方案找出来
		}
	}
}
int main(int argc, char ** arg)
{
	queueSolution(0);
	return 0;
}
	

另外,8皇后的解有92种。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值