13 2n皇后问题

13 2n皇后问题
问题描述 :
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。
问总共有多少种放法?
n小于等于8。
说明:同一条对角线是指包括两条主对角线的所有对角线,n=5时的棋盘从左上往右下有9条对角线,从右上往左下也有9条对角线。

比如,棋盘为:
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
表示一个4*4的棋盘,所有位置都可放皇后。
则可知有2种放法。

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

输出说明 :
输出一个整数,表示总共有多少种放法。

输入范例 :
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
输出范例 :
0

#include<stdio.h>
#include<math.h>
#define max 100
void whiteDFS(int row);
int num,n;
int a[max][max],black[8],white[8];
int isLegal(char type,int row,int col){
	//该位置不能放置
	if(a[row][col]==0){
		return 0;
	}
	//用于是按行逐级筛选,故不用考虑同行情况,只需考虑是否同列,或者在同一对角线上
	//黑皇后
	if(type=='b'){
		for(int i=0;i<row;i++){
			//同列
			if(black[i]==col){
				return 0;
			}
			//同一对角线上 black[]数组里面存放的是对应的行里选取的列的值
			//处于同一对角线上的坐标(x1,y1),(x2,y2) |y1-y2|==|x1-x2|(主对角线,副对角线均要满足) 
			//black[i]对应的是第i行里选取的第几列
			if(abs(black[i]-col)==abs(i-row)){
				return 0;
			}
		}
	}else for(int i=0;i<row;i++){
		if(white[i]==col){
			return 0;
		}
		if(abs(white[i]-col)==abs(i-row)){
			return 0;
		}
	}
	return 1;
}

//先放置黑皇后
void blackDFS(int row){
	//递归返回条件
	if(row==n){
		//转向放置黑皇后
		whiteDFS(0);
		return ;
	}
	else for(int col=0;col<n;col++){
		if(isLegal('b',row,col)){
			black[row]=col;
			//置0
			a[row][col]=0;
			//进入下一行
			blackDFS(row+1);
			//恢复
			a[row][col]=1;
			black[row]=-1;
		}
	}
}
//放置白皇后
void whiteDFS(int row){
	//递归返回条件
	if(row==n){
		num++;
		return;
	}
	for(int col=0;col<n;col++){
		if(isLegal('w',row,col)){
			white[row]=col;
			//置0
			a[row][col]=0;
			//进入下一行
			whiteDFS(row+1);
			//恢复
			a[row][col]=1;
			white[row]=-1;
		}
	}
}
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			scanf("%d",&a[i][j]);	
		}
	}
	num=0;
	blackDFS(0);
	printf("%d\n",num);
	return 0;
}

总结:

1、判读皇后不太同一对角线上要考虑副对角线的情况

发布了157 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_39910081/article/details/105236869