POJ 3239 -- Solution to the n Queens Puzzle

Posted Amysear

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3239 -- Solution to the n Queens Puzzle相关的知识,希望对你有一定的参考价值。

Solution to the n Queens Puzzle
Time Limit: 1000MS   Memory Limit: 131072K
Total Submissions: 3872   Accepted: 1419   Special Judge

Description

The eight queens puzzle is the problem of putting eight chess queens on an 8 × 8 chessboard such that none of them is able to capture any other. The puzzle has been generalized to arbitrary n × n boards. Given n, you are to find a solution to the n queens puzzle.

Input

The input contains multiple test cases. Each test case consists of a single integer n between 8 and 300 (inclusive). A zero indicates the end of input.

Output

For each test case, output your solution on one line. The solution is a permutation of {1, 2, …, n}. The number in the ith place means the ith-column queen in placed in the row with that number.

Sample Input

8
0

Sample Output

5 3 1 6 8 2 4 7

Source

 
 
解题思路:
 
  1)使用回溯法
  

  解空间树是一棵排列树。

  回溯法排列树的框架为:
      

  

  回溯法的复杂度如下所示:     

     

  高复杂度导致了一个必然的结果——超时。

 1 #include<iostream>
 2 #include<cstdlib>
 3 using namespace std;
 4 int x[310];
 5 int isSolved = 0;
 6 bool Constraint(int t)
 7 {///新加入的为x[t],所以只需判断x[t]与前t-1个棋子是否在同一条斜线上
 8     for(int j=1;j<t;j++)
 9     {
10         if(abs(t-j) == abs(x[t] - x[j]))
11             return 0;
12     }
13     return 1;
14 }
15 
16 void BackTrack(int t,int n)
17 {///t从1开始
18     if(t == n+1 || isSolved == 1)
19     {///只得到一个解
20         ///生成解
21         if(isSolved == 0)
22         {
23             for(int k = 1;k<=n;k++)
24             {
25                 cout<<x[k];
26                 if(k != n) cout<<" ";
27                 else cout<<endl;
28             }
29         }
30         isSolved = 1;
31         return;
32     }else{
33         for(int i=t;i<=n;i++)
34         {
35             swap(x[t],x[i]);
36             if(Constraint(t) && isSolved == 0)
37                 BackTrack(t+1,n);
38             swap(x[t],x[i]);
39         }
40     }
41 }
42 
43 int main()
44 {
45     int n;
46     while(cin>>n && n!=0)
47     {
48         isSolved = 0;
49         for(int i=0;i<=n;i++)
50             x[i] = i;
51         BackTrack(1,n);
52     }
53     return 0;
54 }

 

 

  M皇后问题: 在M×M格的国际象棋上摆放M个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。 
  根据场景,又有三种衍生问题: 
  ① 共有多少种摆法(即有多少种可行解) 
  ② 求出所有可行解 
  ③ 求任意一个可行解

  问题① 属于 禁位排列 问题,目前是存在通项公式直接求解的。 
  问题② 属于 搜索 问题,在网上也有多种解法,主流是 回溯法(另有衍生的位运算变种算法),但不管如何优化,回溯法都有一个致命的问题:M值不能过大(一般M=30已是极限)。 
  问题③ 属于 问题② 的子集,因此很多人的切入点依然是回溯法,也有启发式算法的解法:如遗传算法、还有刘汝佳在《算法艺术与信息学竞赛》提出的启发式修补算法。启发式算法在M<10000左右都是可解的,但是因为启发式算法均存在随机性,收敛速度视不同的收敛因子而变化(我看过某篇论文称启发式算法在M=10000时的耗时等价于回溯法M=30的耗时)。

  但早在1969年, 问题③ 的解就被E. J. Hoffman、J. C. Loessi 和R. C. Moore找到了潜在的数学规律,通过推导出数学公式,利用 构造法 使得该问题可在O(1) 的时间复杂度得到解

      2)构造法

  目前网上流传的通解公式,则是为了便于编程,在坐标变换后得到的:
  变换坐标后的求解公式如下:
  ① 当m mod 6 != 2 且 m mod 6 != 3时:
  (A1):[2,4,6,8,...,m], [1,3,5,7,...,m-1] (m为偶)
  (A2):[2,4,6,8,...,m-1], [1,3,5,7,...,m-2], [m] (m为奇)

  ② 当m mod 6 == 2 或 m mod 6 == 3时,
  令 n= m / 2 (m为偶数) 或 n = (m-1)/2 (m为奇数)
  (B1):[n,n+2,n+4,...,m], [2,4,...,n-2], [n+3,n+5,...,m-1], [1,3,5,...,n+1] (m为偶,n为偶)
  (B2):[n,n+2,n+4,...,m-1], [1,3,5,...,n-2], [n+3,...,m], [2,4,...,n+1] (m为偶,n为奇)
  (B3):[n,n+2,n+4,...,m-1], [2,4,...,n-2], [n+3,n+5,...,m-2], [1,3,5,...,n+1], [m] (m为奇,n为偶)
  (B4):[n,n+2,n+4,...,m-2], [1,3,5,...,n-2], [n+3,...,m-1], [2,4,...,n+1], [m] (m为奇,n为奇)

  上面有六条解序列:
  一行一个序列(中括号是我额外加上的,以便辨认子序列)
  第i个数为j,表示在第i行j列放一个皇后.
  子序列与子序列之间的数序是连续关系(无视中括号就可以了), 所有子序列内j的递增值为2

  证明:N皇后问题 - 构造法原理与证明: 时间复杂度O(1)
 
 1 #include<iostream>
 2 using namespace std;
 3 void Print(int x,int y)
 4 {
 5     for(int t = x;t<=y;t+=2)
 6     {
 7         cout<<t;
 8         if(t != y) cout<<" ";
 9     }
10 }
11 int main()
12 {
13     int m;
14     while(cin>>m && m != 0)
15     {
16         if(m%6 != 2 && m %6 !=3)
17         {
18             if(m%2 == 0)//m为偶数
19             {
20                 Print(2,m);cout<<" ";Print(1,m-1);cout<<endl;
21             }else{
22                 Print(2,m-1);cout<<" ";Print(1,m);cout<<endl;
23             }
24         }else{
25             int n = m/2;
26             if(m%2==0 && n%2==0)
27             {
28                 Print(n,m);cout<<" ";Print(2,n-2);cout<<" ";Print(n+3,m-1);cout<<" ";Print(1,n+1);cout<<endl;
29             }else if(m%2 == 0 && n%2 == 1)
30             {
31                 Print(n,m-1);cout<<" ";Print(1,n-2);cout<<" ";Print(n+3,m);cout<<" ";Print(2,n+1);cout<<endl;
32             }else if(m%2 == 1 && n%2 == 0)
33             {
34                 Print(n,m-1);cout<<" ";Print(2,n-2);cout<<" ";Print(n+3,m-2);cout<<" ";Print(1,n+1);cout<<m;cout<<endl;
35             }else{
36                 Print(n,m-2);cout<<" ";Print(1,n-2);cout<<" ";Print(n+3,m-1);cout<<" ";Print(2,n+1);cout<<m;cout<<endl;
37             }
38         }
39 
40     }
41     return 0;
42 }

 

以上是关于POJ 3239 -- Solution to the n Queens Puzzle的主要内容,如果未能解决你的问题,请参考以下文章

How to Creat DLL(Dynamic link library)

poj2891 Strange Way to Express Integers

Poj2761Feed the dogs(主席树)

[POJ 1739] Tony's Tour

Solution to Triangle by Codility

poj2449--Remmarguts' Date------第k短路