一篇文章带你快速搞懂 2n皇后问题

题目描述:

给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条斜线(包括正负斜线)上,任意的两个白皇后都不在同一行、同一列或同一条斜线(包括正负斜线)上。问共有多少种放法?n<=8。

输入:

第一行输入一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数。如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。

输出:

输出所有可以按照要求摆放n*n的棋盘,若没有则不输出。
注意:数字2表示可以放置黑皇后,数字3表示可以放置白皇后。
最后输出一个整数,表示总共有多少种放法。

思路:

先摆放完黑皇后,再摆放白皇后。
从第1行到第n行依次摆放皇后。
摆放皇后检查哪列可以摆放。
注意:只有当mp[][]为1时才可以摆放皇后。因为摆放此皇后之前可能已经摆放了其他皇后。例如,摆放白皇后时,某位已摆放了黑皇后,数字变成了2!

注:其他细节问题均已注释在代码中!

代码如下:

#include<cstdio>
#include<cmath>
int n,ans;
int mp[9][9];
//mp[][]为0则不可放置皇后,为1则可放置皇后,为2则可以放置黑皇后,为3则可以放置白皇后
bool judge(int x,int y,int k){
	//判断(x,y)位置的k皇后是否与前x-1行的k皇后是否冲突
	if(x==1)
		return true;
	for(int i=1;i<x;++i){
		if(mp[i][y]==k)
			return false;
		for(int j=1;j<=n;++j){
			if(abs(x-i)==abs(y-j)&&mp[i][j]==k){
				return false;
			}
		}
	}
	return true;
} 
void dfs(int x,int k){
	if(x==n+1&&k==3){		//黑白皇后放置完毕
		++ans;
		for(int i=1;i<=n;++i){
			for(int j=1;j<=n;++j){
				printf("%-2d",mp[i][j]);
			}
			printf("\n");
		}
		printf("\n");
		return;
	} 
	if(x==n+1&&k==2){		//黑皇后放置完毕,开始放置白皇后
		dfs(1,3);
		return;
	}
	for(int i=1;i<=n;++i){	//对x行k皇后检查哪列可以放置 
		if(mp[x][i]==1&&judge(x,i,k)){
			mp[x][i]=k;
			dfs(x+1,k);
			mp[x][i]=1;    //因为是求所有解,所以需要回溯!
		}
	}
}
int main(){
	scanf("%d",&n);			//输入棋盘规格 
	for(int i=1;i<=n;++i){	//输入棋盘 
		for(int j=1;j<=n;++j){
			scanf("%d",&mp[i][j]);
		}
	}
	printf("\n");
	dfs(1,2);
	printf("%d",ans);
	return 0;
} 

运行结果:

大一小白编写代码水平有限,如果对您有帮助,请点赞支持,感谢!
大一小白编写代码水平有限,如果对您有帮助,请点赞支持,感谢!
大一小白编写代码水平有限,如果对您有帮助,请点赞支持,感谢!

最后,如果你也是一名小白,欢迎添加博主微信:xinglibao465 互相交流进步!感谢!
最后,如果你也是一名小白,欢迎添加博主微信:xinglibao465 互相交流进步!感谢!
最后,如果你也是一名小白,欢迎添加博主微信:xinglibao465 互相交流进步!感谢! 

发布了23 篇原创文章 · 获赞 10 · 访问量 1744

猜你喜欢

转载自blog.csdn.net/weixin_45953673/article/details/105086632