Problem D: 2n皇后问题
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 25 Solved: 19
[ Submit][ Status][ Web Board]
Description
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
Input
输入的第一行为一个整数n,表示棋盘的大小。接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
Output
输出一个整数,表示总共有多少种放法。
Sample Input
4 1 1 1 11 1 1 11 1 1 1 1 1 1 14 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Sample Output
20
解题思路:方法应该很多,我的办法是按照传统的N皇后问题来做,每行先放白皇后,再放同行的黑皇后,再放下一行的白皇后......直到放n+1行白皇后的时候就得到一个解。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int mp[10][10];
int rW[20],rB[20];//i-j+n左斜线
int mW[20],mB[20];//i+j右斜线
int lW[10],lB[10];//j竖行
int ans;
void DFSw(int k,int n)//放白皇后
{
void DFSb(int k,int n);
if(k>n)
{
ans++;
return;
}
int i=k;
for(int j=1;j<=n;j++)
{
if(mp[i][j]&&rW[i-j+n]==0&&mW[i+j]==0&&lW[j]==0)
{
mp[i][j]=0;
rW[i-j+n]=1;
mW[i+j]=1;
lW[j]=1;
DFSb(k,n);//放完白皇后立马放同行的黑皇后
//cout<<"w "<<k<<' '<<j<<endl;
mp[i][j]=1;
rW[i-j+n]=0;
mW[i+j]=0;
lW[j]=0;
}
}
}
void DFSb(int k,int n)
{
int i=k;
for(int j=1;j<=n;j++)
{
if(mp[i][j]&&rB[i-j+n]==0&&mB[i+j]==0&&lB[j]==0)
{
mp[i][j]=0;
rB[i-j+n]=1;
mB[i+j]=1;
lB[j]=1;
DFSw(k+1,n);//放完黑皇后立马放下一行的白皇后
//cout<<"b "<<k<<' '<<j<<endl;
mp[i][j]=1;
rB[i-j+n]=0;
mB[i+j]=0;
lB[j]=0;
}
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&mp[i][j]);
}
}
memset(rW,0,sizeof(rW));
memset(rB,0,sizeof(rB));
memset(mW,0,sizeof(mW));
memset(mB,0,sizeof(mB));
memset(lW,0,sizeof(lW));
memset(lB,0,sizeof(lB));
DFSw(1,n);
printf("%d\n",ans);
}
return 0;
}
/**************************************************************
Problem: 1803
User: HUCM201702
Language: C++
Result: Accepted
Time:80 ms
Memory:1480 kb
****************************************************************/