POJ3239-Solution to the n Queens Puzzle

全解题报告索引目录 -> 【北大ACM – POJ试题分类

转载请注明出处:http://exp-blog.com/2018/06/15/pid-420/

-------------------------------------------------------------------------



N皇后问题,由于n的规模较大,可使用构造法解题。


构造法原理:

    英文原文(原作者E.J.Hoffman): http://penguin.ewu.edu/~trolfe/QueenLasVegas/Hoffman.pdf 

    原文下载:http://download.csdn.net/download/lyy289065406/10184847


    中文译文(本人亲译,补充了现在网上流传的 【构造法公式的推导过程

        http://exp-blog.com/2018/06/16/pid-429/

    译文下载:http://download.csdn.net/download/lyy289065406/10184900


  1. /*
  2. Author: Exp
  3. Date: 2017-12-27
  4. Code: POJ 3239
  5. Problem: Solution to the n Queens Puzzle
  6. URL: http://poj.org/problem?id=3239
  7. */
  8. /*
  9. 题意分析:
  10. N皇后问题:
  11. 在NxN棋盘内 纵、横、斜不重叠放置棋子,
  12. 当给定N (N ∈ [8, 300]) 时, 输出任意一种解法
  13. 解题思路:
  14. (为了便于下文分析讨论,此处开始修正为“M皇后问题”)
  15. 【禁位排列】的一种题型。
  16. 传统解法是【回溯法(DFS+剪枝)】,但本题N值过大,回溯法会爆栈.
  17. LRJ的《算法艺术与信息学竞赛》提出的解法是【启发式修补算法】(属于人工智能算法的一种)
  18. 启发式算法在M<10000左右都是可解的,但是因为启发式算法均存在随机性,
  19. 收敛速度视不同的收敛因子而变化(我看过某篇论文称启发式算法在M=10000时的耗时等价于回溯法M=30的耗时)
  20. 这题还有用【构造法】(即通过分析问题潜在的数学规律直接得到解)的通解公式,时间复杂度为O(1)
  21. 通解公式的原理来源是由E.J.Hoffman、J.C.Loessi、R.C.Moore三人在1969年发表的一篇数学论文:
  22. 英文原文: http://penguin.ewu.edu/~trolfe/QueenLasVegas/Hoffman.pdf
  23. 原文下载:http://download.csdn.net/download/lyy289065406/10184847
  24. 中文译文(本人亲译):http://blog.csdn.net/lyy289065406/article/details/78955101
  25. 译文下载:http://download.csdn.net/download/lyy289065406/10184900
  26. 而目前网上流传的通解公式,则是为了便于编程,在坐标变换后得到的:
  27. 变换坐标后的求解公式如下:
  28. ① 当m mod 6 != 2 且 m mod 6 != 3时:
  29. (A1):[2,4,6,8,...,m], [1,3,5,7,...,m-1] (m为偶)
  30. (A2):[2,4,6,8,...,m-1], [1,3,5,7,...,m-2], [m] (m为奇)
  31. ② 当m mod 6 == 2 或 m mod 6 == 3时,
  32. 令 n= m / 2 (m为偶数) 或 n = (m-1)/2 (m为奇数)
  33. (B1):[n,n+2,n+4,...,m], [2,4,...,n-2], [n+3,n+5,...,m-1], [1,3,5,...,n+1] (m为偶,n为偶)
  34. (B2):[n,n+2,n+4,...,m-1], [1,3,5,...,n-2], [n+3,...,m], [2,4,...,n+1] (m为偶,n为奇)
  35. (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为偶)
  36. (B4):[n,n+2,n+4,...,m-2], [1,3,5,...,n-2], [n+3,...,m-1], [2,4,...,n+1], [m] (m为奇,n为奇)
  37. 上面有六条解序列:
  38. 一行一个序列(中括号是我额外加上的,以便辨认子序列)
  39. 第i个数为j,表示在第i行j列放一个皇后.
  40. 子序列与子序列之间的数序是连续关系(无视中括号就可以了), 所有子序列内j的递增值为2
  41. */
  42. #include <iostream>
  43. using namespace std;
  44. /*
  45. * 每隔1个数打印从bgn到end的序列
  46. * @param bgn 起始值(包括)
  47. * @param end 终止值(包括)
  48. */
  49. void print(int bgn, int end);
  50. int main(void) {
  51. int m = 0;
  52. while( cin >> m && m > 0) {
  53. const int mod = m % 6;
  54. const bool mOdd = (m % 2 == 1);
  55. if(mod != 2 && mod != 3) {
  56. // A2
  57. if(mOdd == true) {
  58. print( 2, m - 1);
  59. print( 1, m);
  60. // A1
  61. } else {
  62. print( 2, m);
  63. print( 1, m - 1);
  64. }
  65. } else {
  66. int n = m / 2;
  67. const bool nOdd = (n % 2 == 1);
  68. if(mOdd == true) {
  69. // B4
  70. if(nOdd == true) {
  71. print(n, m - 2);
  72. print( 1, n - 2);
  73. print(n + 3, m - 1);
  74. print( 2, n + 1);
  75. print(m, m);
  76. // B3
  77. } else {
  78. print(n, m - 1);
  79. print( 2, n - 2);
  80. print(n + 3, m - 2);
  81. print( 1, n + 1);
  82. print(m, m);
  83. }
  84. } else {
  85. // B2
  86. if(nOdd == true) {
  87. print(n, m - 1);
  88. print( 1, n - 2);
  89. print(n + 3, m);
  90. print( 2, n + 1);
  91. // B1
  92. } else {
  93. print(n, m);
  94. print( 2, n - 2);
  95. print(n + 3, m - 1);
  96. print( 1, n + 1);
  97. }
  98. }
  99. }
  100. }
  101. return 0;
  102. }
  103. void print(int bgn, int end) {
  104. for( int i = bgn; i <= end; i+= 2) {
  105. cout << i << ' ';
  106. }
  107. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值