dfs解决n皇后问题

n皇后问题

题目链接

题目描述

给定一个 n,要求在 n×n 格的棋盘上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。

解题思路

我们从第一行到第n行放置,在放置每一行时,我们从第1列遍历到第n列,查看每一列是否放置过,且要判断斜对角线上是否放置过。思路比较简单。

我自己认为的一个难点就是,怎样判断斜对角线上是否放置过棋子。我们把棋盘看成一个个小方块,行我们从上到下编号为1…n,列我们从左到右编号为1…n,对于右下的对角线,我们不难发现,它的行列对应的值分别加 1, 那么行列的差值便是相等的。对于左下的对角线,我们观察可以发现,对应的行和列的数值是相反变化的,若行加1,则列减一,若列加1,则行减一。我们就可以通过判断,行+列的值和行-列的值是否出现过来判断左下和右下斜对角线是否放置过棋子。

代码如下

#include<bits/stdc++.h>
using namespace std;

int n;
int a[11];
bool vis[11]; //标记列是否放置过
map<int,int>leftdown; //标记左下对角线是否放置过,放置过则对应的(行+列)置为1
map<int,int>rightdown; //标记右下对角线是否放置过,放置过则对应的行-列)置为1
int an; //用来记录可行方案的数量
void dfs(int x) { //x表示当前要放置棋子所在行为x
	if(x == n+1) {
		an++;
		for(int i = 1; i<= n; i++) {
			printf("%d ",a[i]);
		}
		printf("\n");
		return;
	}
	for(int i = 1; i<= n; i++) {
		if(!vis[i] && leftdown[x-i]==0 && rightdown[x+i]==0) {
			a[x] = i;
			vis[i] = true; //标记列
			leftdown[x-i] = 1; //左下对角线
			rightdown[x+i] = 1; //右下对角线
			dfs(x+1);
			vis[i] = false;
			leftdown[x-i] = 0;
			rightdown[x+i] = 0;
		}
	}
	return;
}
int main() {
	scanf("%d",&n);
	memset(vis,false,sizeof(vis));
	dfs(1);
	if(an == 0) printf("no solute!\n");
} 

猜你喜欢

转载自blog.csdn.net/weixin_43966538/article/details/106325547