2n皇后问题(计蒜客)

来源:互联网 发布:植物生长算法代码 编辑:程序博客网 时间:2024/06/05 02:24

时间限制 1000ms内存限制 65536K

题目描述

给定一个 n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入 n 个黑皇后和 n 个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n 小于等于 8。

输入格式

输入的第一行为一个整数 n,表示棋盘的大小。

接下来 n 行,每行 n  0  1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为 0,表示对应的位置不可以放皇后。

输出格式

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

样例输入1

4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1

样例输出1

2

样例输入2

4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1

样例输出2

0

思路

       这道题可以看成是两个八皇后问题,我们可以先把所有的黑皇后放入棋盘中的合适位置,这里用和正常八皇后问题的递归函数求解即可,然后在黑皇后全部放入的情况下尝试放入白皇后,当所有的白皇后都可被放入时即存在一组解。只是这里判断有无冲突的函数bool notDanger(int r, int c)有所区别,对于黑皇后而言,除了当前位置不能与之前的皇后同列同斜线以外,这个位置必须是可放位置,即chess[r][c]==1,对白皇后同理,而且白皇后不能处于和已经放好的黑皇后相同的位置上面去。

 

代码

 

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int n, ans;int chess[10][10];int x1[10], x2[10];//先放入黑皇后,再放入白皇后bool notDanger1(int r, int c) {//判断黑皇后是否冲突if (0 == chess[r][c]) return false;for (int i = 0; i < r; i++) {if (x1[i] == c) return false;if (abs(r - i) == abs(c - x1[i])) return false;}return true;}bool notDanger2(int r, int c) {//判断白皇后是否冲突if (0 == chess[r][c]) return false;if (x1[r] == c) return false;//注意黑白皇后不能重叠for (int i = 0; i < r; i++) {if (x2[i] == c) return false;if (abs(r - i) == abs(c - x2[i])) return false;}return true;}void queen2(int k) {//在第k行放入白皇后if (k == n) {ans++;return;}for (int i = 0; i < n; i++) {if (notDanger2(k, i)) {x2[k] = i;queen2(k + 1);x2[k] = -1;}}}void queen1(int k) {//在第k行放入黑皇后if (k == n) {queen2(0);return;}for (int i = 0; i < n; i++) {if (notDanger1(k, i)) {x1[k] = i;queen1(k + 1);x1[k] = -1;}}}int main() {while (scanf("%d", &n) == 1) {ans = 0;memset(x1, -1, sizeof(x1));memset(x2, -1, sizeof(x2));for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++)scanf("%d", &chess[i][j]);}queen1(0);printf("%d\n", ans);}return 0;}