题目链接:http://lx.lanqiao.cn/problem.page?gpid=T68
问题描述
给定一个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
解题思路:
1.这一题和n皇后问题特别类似,如果n皇后问题不太懂, 可以 点击这里!!,里面详细讲述了n皇后问题的解法。
2.下面说一下不同的地方,解决2n皇后问题(这里假设是黑皇后和白皇后),可以先按n皇后问题搜索白皇后(黑皇后也可以),等搜索到一种白皇后的解法之后,可以开始搜索黑皇后了,等搜索到一种黑皇后的摆法,这样就算搜索到了一种2n皇后的摆法(代码中写了两个搜索函数,两个判断函数,搜索函数和判断函数几乎和n皇后问题里面的一样),具体来看代码
代码
#include<iostream> #include<math.h> using namespace std; int n,book[10][10],sum; int white[10],black[10]; int checkw(int k)//k行,white[k]列 { for(int i=1;i<k;i++) { if(white[i]==white[k]||abs(k-i)==abs(white[k]-white[i]))//同一列或者对角线 return 0; } return 1; } int checkb(int k)//k行,black[k]列 { for(int i=1;i<k;i++) { if(black[i]==black[k]||abs(k-i)==abs(black[k]-black[i]))//同一列或者对角线 return 0; } return 1; } void dfsb(int row) { if(row>n) { sum++; return ; } for(int i=1;i<=n;i++) { black[row]=i; if(checkb(row)==1&&book[row][i]==1&&white[row]!=i) { dfsb(row+1); } } } void dfsw(int row) { if(row>n) { dfsb(1); return ; } for(int i=1;i<=n;i++) { white[row]=i; if(checkw(row)==1&&book[row][i]==1) { dfsw(row+1); } } } int main() { int i,j; cin>>n; for(i=1;i<=n;i++) for(j=1;j<=n;j++) cin>>book[i][j]; dfsw(1); cout<<sum<<endl; return 0; }