N皇后问题(回溯做法)

题目描述

相信大家都听过经典的“八皇后”问题吧?这个游戏要求在一个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;
}


猜你喜欢

转载自www.cnblogs.com/liaoshuangqi/p/10838097.html