蓝桥杯 试题 基础练习 2n皇后问题(附n皇后代码)

心路历程:

之前并没有系统的学过递归和搜索,在学这道题前先学习了深搜、递归,并敲掉了经典N皇后,因此理解起来难度也不是很大。 没有基础的同学一定要先把N皇后看会在碰这道题。下面会有N皇后逐步讲解的视频链接和N皇后源码。如果大家已经学会N皇后,自行跳过这一步,直接看2N皇后源码就行了,代码里有详细的注释。


传送门→N皇后问题(N Queens) 从示意图到代码
PS:这个视频较长,看到理解回溯的原理就可以了。


经典N皇后源码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 15;		//这种定义方法比#define要好
int q[maxn];
int m, sum = 0; 
//place函数:这个位置是否可以放置 
int place(int k) {
	for(int i = 1; i < k; i++) 		//当前行皇后是否与前K行皇后有冲突 
	//若当前皇后所在行数-某一行皇后所在行数=当前皇后所在列数-某一行皇后所在咧数。 或 当前皇后所在列数=某一行皇后所在列数。 则不符合。 
		if(abs(k-i) == abs(q[k]-q[i]) || q[k] == q[i])	 
			return 0;
	return 1;
}
void dfs(int step) {
	if(step > m) { sum++; return; }		//终止条件 
	for(int i = 1; i <= m; i++) {
		q[step] = i;				//q数组里的值是该皇后所在列数 
		if(place(step)) dfs(step+1);
	}
}
int main() {
	int n; cin >> n; while(n--) {
		sum = 0;
		cin >> m; 
		dfs(1);
		cout << sum << endl; 
	}
	return 0;
} 

解2N皇后的注意点:

1、独立理解出n皇后回溯解法。
2、本题特点:在原有n皇后的基础上加了一个判断,如果是1则可以走, 如果是0,无论如何,这个点都无法参与运算。
3、2n皇后特点:判断完黑皇后的位置后,将黑皇后所在位置置0,判断白皇后,若在此种情况下白皇后也可以全部放置,则可能的组合+1。

2N皇后源码:

#include<bits/stdc++.h>
using namespace std;
int queen[8][8];					//棋盘 
int A[8], B[8];						//分别存放白、黑皇后可取的列数。 
int cnt, t;							//cnt=可能数,t=棋盘尺寸 
void dfs_black(int ccur) {			//ccur=0,从0开始回溯 
	if(ccur == t) cnt++;
	else for(int i = 0; i < t; i++) {
		if(queen[ccur][i]) {		//1为可以放置 
			B[ccur]=i;				//存入当前列 
			int ok = 1;				
			for(int j = 0; j < ccur; j++) //判断前curr行是否有冲突 
				//若当前皇后列数=某一行皇后列数 或 当前行皇后所在行-当前皇后所在的列=某一行皇后所在行-某一行皇后所在的列 
				//写法2:if(B[ccur]==B[j]||ccur-B[ccur]==j-B[j]||ccur+B[ccur]==j+B[j]) 
				if(B[ccur]==B[j]||abs(ccur-j)==abs(B[ccur]-B[j]))
					ok = 0;			//则该位置不可取 
			if(ok) dfs_black(ccur+1);	//若可取,则递归至curr+1 
		}
	}
}
void dfs_white(int cur) {
	if(cur == t) {				//若白皇后遍历完则执行,否则跳到else 
		for(int k = 0; k < t; k++) 
			queen[k][A[k]]=0; 	//该位置放了白皇后,不可以放别的。 
		dfs_black(0);
		for(int k = 0; k < t; k++) 
			queen[k][A[k]]=1;	//状态重置很重要 
	}
	else for(int i = 0; i < t; i++){	//从第0行开始遍历 
		if(queen[cur][i]) {		//若可以放置(为1) 
			A[cur]=i;			//则放置 
			int ok = 1;			
			for(int j = 0; j < cur; j++) 
				if(A[cur]==A[j]||abs(cur-j)==abs(A[cur]-A[j]))
					ok = 0;
			if(ok) dfs_white(cur+1);
		}
	} 
} 
int main() {
	cin >> t;					//皇后的个数及行/列数 
	for(int i = 0; i < t; i++) 
		for(int j = 0; j < t; j++)
			cin >> queen[i][j];		//输入棋盘
	dfs_white(0);					//从0开始回溯
	cout << cnt << endl; 
	return 0;
}
发布了73 篇原创文章 · 获赞 61 · 访问量 4756

猜你喜欢

转载自blog.csdn.net/weixin_43899069/article/details/104572528
今日推荐