问题描述
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
2
样例输入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
0
先放黑 放完后放白,在白里面统计次数
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int n;
int a[10][10];
int t = 0;
/*void print()
{
printf("No. %d\n", t++);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d ", a[j][i]);
}
printf("\n");
}
}*/
bool judge(int x, int y)
{
for(int i=0; i<x; i++)
{//竖直方向||左上方 || 右上方
if(a[i][y]==2 || (y-i-1>=0 && (a[x-i-1][y-i-1]==2)) || (y+i+1<n && (a[x-i-1][y+i+1] == 2)))
return false;
}
return true;
}
bool judge2(int x, int y)//有错
{
for(int i=0; i<x; i++)
{//竖直方向||左上方 || 右上方
if(a[i][y]==3 || ((y-i-1>=0 && (a[x-i-1][y-i-1]) ==3 ))|| (y+i+1<n && (a[x-i-1][y+i+1] == 3)))
return false;
}
return true;
}
void dfs2(int num)
{
if (num >= n){
//print();
//
t++;
// return;
}
for (int i = 0; i < n; i++)
{
if (a[num][i]==1&&judge2(num, i))
{
a[num][i] = 3;
dfs2(num + 1);
a[num][i] = 1;
}
}
}
int dfs1(int num)
{
if (num >= n){
//print();
dfs2(0);//白
// return 0;
}
for (int i = 0; i < n; i++)
{
// hang[num] = i;
if (a[num][i]==1&&judge(num, i))
{
a[num][i] = 2;
if(dfs1(num + 1))
return 1;
a[num][i] = 1;
}
}
return 0;
}
int main()
{
cin >> n;
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
cin >> a[i][j];
dfs1(0);//黑
printf("%d\n", t);
return 0;
}