题目描述
相信大家都听过经典的“八皇后”问题吧?这个游戏要求在一个8×8的棋盘上放置8个皇后,使8个皇后互相不攻击(攻击的含义是有两个皇后在同一行或同一列或同一对角线上)。
桐桐对这个游戏很感兴趣,也很快解决了这个问题。可是,他想为自己增加一点难度,于是他想求出n皇后的解的情况。
你能帮助她吗?
输入输出格式
输入格式:
一行,仅有一个数n(1≤n≤14),表示为n皇后问题。
输出格式:
输出仅有一个数,表示n皇后时问题的解法总数。
输入输出样例
8
92
首先我们想到用二维数组做,但是二维数组肯定会超时,所以我们用降维做法,
注:(没有用对称的代码):
没有运用对称必超时
可能13皇后都过不了.....
#include<iostream>
using namespace std;
int q[100][100],box,n;
void queen(int k)
{
if(k>n)
{
box++;
if(box>3) return;
}
for(int i=1;i<=n;i++)
{
if(q[0][i]==0&&q[1][k+i]==0&&q[2][k-i+n]==0)
{
q[0][i]=1;
q[1][k+i]=1;
q[2][k-i+n]=1;
queen(k+1);
q[0][i]=0;
q[1][k+i]=0;
q[2][k-i+n]=0;
}
}
}
int main()
{
cin>>n;
queen(1);
cout<<box;
return 0;
}
原先在棋盘上(1,1)位置有棋子,就把数组q[1][1]标记为1
然后我们可以吧它改为(1,1)有棋子就把q[1]标记为1,这样可以减少时间复杂度,
13皇后可以压线过
然后我们再优化,用数组计数,我们发现,第i行的棋子会在第x+ix+i条正对角线上,
会在第x?i+nx?i+n条反对角线上,就用数组计数,每访问一次这个对角线,就把它标记为1,
即可减少超时
可是这个做法对于14皇后还需要大约两秒,
我们再优化。
发现这个棋盘具有对称性,以4皇后为例,举例如下
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
如果这个做法可行,那么下列做法
0 0 1 0
1 0 0 0
0 0 0 1
0 1 0 0
也是可行的,所以第一行只需要放到(n+1)/2(n+1)/2就可以了
至此,基本可以吧14皇后优化至1秒内
以下为优化代码:
#include<iostream> using namespace std; int q[10][100],box,n; void queen1(int k) { if(k>n) { box+=2; return; } for(int i=1;i<=n;i++) { if(q[0][i]==0&&q[1][k+i]==0&&q[2][k-i+n]==0) { q[0][i]=1; q[1][k+i]=1; q[2][k-i+n]=1; queen1(k+1); q[0][i]=0; q[1][k+i]=0; q[2][k-i+n]=0; } } } void queen2(int k) { if(k>n) { box+=2; return; } for(int i=1;i<=n/2;i++) { if(q[0][i]==0&&q[1][k+i]==0&&q[2][k-i+n]==0) { q[0][i]=1; q[1][k+i]=1; q[2][k-i+n]=1; queen1(k+1); q[0][i]=0; q[1][k+i]=0; q[2][k-i+n]=0; } } } int main() { cin>>n; for(int i=1;i<=n/2;i++) { q[0][i]=1; q[1][i+1]=1; q[2][1-i+n]=1; queen1(2); q[0][i]=0; q[1][i+1]=0; q[2][1-i+n]=0; } if(n%2==1)//当n为奇数时 { q[0][n/2+1]=1; q[1][(n/2+1)+1]=1; q[2][1-(n/2+1)+n]=1; queen2(2); } cout<<box; return 0; }