2n皇后问题
Problem Description
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
Input
输入的第一行为一个整数n,表示棋盘的大小。 n小于等于8
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
Output
输出一个整数,表示总共有多少种放法。
Sample Input
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
Sample Output
2
方法一:典型的递归算法(全排列的思想来做)
#include<iostream>
#include<algorithm>
using namespace std;
int disable[11] = {0}; //disable[2]=3第2行第3列不能放皇后
int white_p[11], black_p[11];
int n;
int counts = 0;
bool black_hashTable[11] = {false}, white_hashTable[11] = {false};
void solution_white(int index) //index表示行号
{
//递归边界
if(index == n+1)
{
bool flag = true;
for(int i=1;i<=n;i++)
{
// if(white_p[i] == black_p[i])
// {
// flag = false;
// break;
// }
for(int j=i+1; j<=n; j++)
{
if(abs(j-i) == abs(white_p[j] - white_p[i]))
{
flag = false;
break;
}
}
}
if(flag){
counts += 1;
}
return;
}
//
for(int i=1;i<=n;i++) //黑皇后的正向遍历
{
if(white_hashTable[i] == false && black_p[index] != i && disable[index] != i)
{
white_p[index] = i;
white_hashTable[i] = true;
solution_white(index+1);
white_hashTable[i] = false;
}
}
}
void solution_black(int index) //index表示行号
{
//递归边界
if(index == n+1)
{
bool flag = true;
for(int i=1;i<=n;i++)
for(int j =i+1; j<=n; j++)
{
if(abs(j-i) == abs(black_p[j] - black_p[i]))
{
flag = false;
break;
}
}
if(flag)
solution_white(1);
return;
}
//
for(int i=1;i<=n;i++) //黑皇后的正向遍历
{
if(black_hashTable[i] == false && disable[index] != i)
{
black_p[index] = i;
black_hashTable[i] = true;
solution_black(index+1);
black_hashTable[i] = false;
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
int temp;
cin>>temp;
if(temp==0)
disable[i] = j;
}
solution_black(1);
cout<<counts<<endl;
return 0;
}
简单优化一下:
#include<iostream>
#include<algorithm>
using namespace std;
int disable[11] = {0}; //disable[2]=3第2行第3列不能放皇后
int white_p[11], black_p[11];
int n;
int counts = 0;
bool black_hashTable[11] = {false}, white_hashTable[11] = {false};
void solution_white(int index) //index表示行号
{
//递归边界
if(index == n+1)
{
// bool flag = true;
// for(int i=1;i<=n;i++)
// {
// for(int j=i+1; j<=n; j++)
// {
// if(abs(j-i) == abs(white_p[j] - white_p[i]))
// {
// flag = false;
// break;
// }
// }
// }
// if(flag)
counts += 1;
return;
}
//
for(int i=1;i<=n;i++) //黑皇后的正向遍历
{
if(white_hashTable[i] == false && black_p[index] != i && disable[index] != i)
{
bool flag = true;
for(int j=1;j<index;j++)
{
if(abs(index-j) == abs(i-white_p[j])){
flag = false;
break;
}
}
if(flag){
white_p[index] = i;
white_hashTable[i] = true;
solution_white(index+1);
white_hashTable[i] = false;
}
}
}
}
void solution_black(int index) //index表示行号
{
//递归边界
if(index == n+1)
{
// bool flag = true;
// for(int i=1;i<=n;i++)
// for(int j =i+1; j<=n; j++)
// {
// if(abs(j-i) == abs(black_p[j] - black_p[i]))
// {
// flag = false;
// break;
// }
// }
// if(flag)
solution_white(1);
return;
}
//
for(int i=1;i<=n;i++) //黑皇后的正向遍历
{
if(black_hashTable[i] == false && disable[index] != i)
{
bool flag = true;
for(int j=1;j<index;j++)
{
if(abs(index-j) == abs(i-black_p[j])){
flag = false;
break;
}
}
if(flag){
black_p[index] = i;
black_hashTable[i] = true;
solution_black(index+1);
black_hashTable[i] = false;
}
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
int temp;
cin>>temp;
if(temp==0)
disable[i] = j;
}
solution_black(1);
cout<<counts<<endl;
return 0;
}