算法学习2.1递归之n皇后问题

用递归替代多重循环

n皇后问题:

输入整数n, 要求n个国际象棋的皇后,摆在n*n的棋盘上,互相不能攻击,输出全部方案。

输入一个正整数N,则程序输出N皇后问题的全部摆法。
输出结果里的每一行都代表一种摆法。行里的第i个数字如果是n,
就代表第i行的皇后应该放在第n列。
皇后的行、列编号都是从1开始算。
样例输入:
4
样例输出:
2 4 1 3
3 1 4 2

截图

代码思路

首先一行行的排皇后,在排某行发生冲突的时候测试下一个位置,如果没有冲突直接k+1递归调用函数进行下一行排,但是程序中递归处有争议,其中有郭炜老师和学生的争议

争议处

学生:如题,听了之后还是不太明白,为什么第一行的皇后放在第二列,调用NQueen(2),而NQueen(2)尝试了所有位置都没办法放置第二行的皇后,课件里说会返回到NQueen(1),按课件里老师讲的理由我无法确定这一点必然发生,因为我们并没有在程序里设置调用NQueen失败之后怎么做,不知道还有没有其他理解这一个关键步骤的方法,是不是还与栈之类的东西有关?

老师:事实是这样没错,就是自己不知道为什么会这样,我尝试了用多重循环的方法去理解这个步骤,也失败了,按我现有的知识,执行QUeen(2)往下无法执行并不能直接导致程序会回到上一层这个结果。不过按照这个思路,我自己也无法说服自己多重的for循环在下一层循环结束之后会返回到上一层循环了。暂时就按多重循环来理解这个步骤,QUueen(2)失败之后这一层的循环就结束了,只能回到上一层。如果课件里在这里能看一下单步执行的结果可能会更好。我自己会再尝试一下的。

期待有缘人给我解释一下

#include <iostream> 
#include <cmath> 
using namespace std; 
int N;
int queenPos[100]; 
//用来存放算好的皇后位置。最左上角是(0,0)
void NQueen( int k);
int main()
{
	cin >> N;
	NQueen(0); //从第0行开始摆皇后
	return 0;
}
void NQueen( int k) //在0~k-1行皇后已经摆好的情况下,摆第k行及其后的皇后
{
		int i;
        if( k == N ) { // N 个皇后已经摆好
			for( i = 0; i < N;i ++ )
					cout << queenPos[i] + 1 << " "; 
			cout << endl;
			return ;
	}
	for( i = 0;i < N;i ++ ) { //逐尝试第k个皇后的位置
		int j;
		for( j = 0; j < k; j ++ ) {
			//和已经摆好的 k 个皇后的位置比较,看是否冲突
			if( queenPos[j] == i || 
			//queenPos[j]表示第j行皇后的位置,这里是看是否满足第j行皇后的列数是否为i
			     abs(queenPos[j] - i) == abs(k-j)) {//看第k行皇后列之差是否与行之差相等
                 break; //冲突,则试下一个位置
				 }
		}
		if( j == k ) { //当前选的位置 i 不冲突
				queenPos[k] = i; //将第k个皇后摆放在位置 i
				NQueen(k+1);
		}
	}//for(i = 0;i < N; i++)
}
发布了20 篇原创文章 · 获赞 1 · 访问量 161

猜你喜欢

转载自blog.csdn.net/weixin_42503072/article/details/104392067