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、判读皇后不太同一对角线上要考虑副对角线的情况