1. /* Jeff Somers
  2. *
  3. * Copyright (c) 2002
  4. *
  5. * jsomers@alumni.williams.edu
  6. * or
  7. * allagash98@yahoo.com
  8. *
  9. * April, 2002
  10. *
  11. * Program: nq
  12. *
  13. * Program to find number of solutions to the N queens problem.
  14. * This program assumes a twos complement architecture.
  15. *
  16. * For example, you can arrange 4 queens on 4 x 4 chess so that
  17. * none of the queens can attack each other:
  18. *
  19. * Two solutions:
  20. * _ Q _ _ _ _ Q _
  21. * _ _ _ Q Q _ _ _
  22. * Q _ _ _ _ _ _ Q
  23. * _ _ Q _ and _ Q _ _
  24. *
  25. * Note that these are separate solutions, even though they
  26. * are mirror images of each other.
  27. *
  28. * Likewise, a 8 x 8 chess board has 92 solutions to the 8 queens
  29. * problem.
  30. *
  31. * Command Line Usage:
  32. *
  33. * nq N
  34. *
  35. * where N is the size of the N x N board. For example,
  36. * nq 4 will find the 4 queen solution for the 4 x 4 chess
  37. * board.
  38. *
  39. * By default, this program will only print the number of solutions,
  40. * not board arrangements which are the solutions. To print the
  41. * boards, uncomment the call to printtable in the Nqueen function.
  42. * Note that printing the board arrangements slows down the program
  43. * quite a bit, unless you pipe the output to a text file:
  44. *
  45. * nq 10 > output.txt
  46. *
  47. *
  48. * The number of solutions for the N queens problems are known for
  49. * boards up to 23 x 23. With this program, I've calculated the
  50. * results for boards up to 21 x 21, and that took over a week on
  51. * an 800 MHz PC. The algorithm is approximated O(n!) (i.e. slow),
  52. * and calculating the results for a 22 x 22 board will take about 8.5
  53. * times the amount of time for the 21 x 21 board, or over 8 1/2 weeks.
  54. * Even with a 10 GHz machine, calculating the results for a 23 x 23
  55. * board would take over a month. Of course, setting up a cluster of
  56. * machines (or a distributed client) would do the work in less time.
  57. *
  58. * (from Sloane's On-Line Encyclopedia of Integer Sequences,
  59. * Sequence A000170
  60. * http://www.research.att.com/cgi-bin/access.cgi/as/njas/sequences/eisA.cgi?Anum=000170
  61. * )
  62. *
  63. * Board Size: Number of Solutions to Time to calculate
  64. * (length of one N queens problem: on 800MHz PC
  65. * side of N x N (Hours:Mins:Secs)
  66. * chessboard)
  67. *
  68. * 1 1 n/a
  69. * 2 0 < 0 seconds
  70. * 3 0 < 0 seconds
  71. * 4 2 < 0 seconds
  72. * 5 10 < 0 seconds
  73. * 6 4 < 0 seconds
  74. * 7 40 < 0 seconds
  75. * 8 92 < 0 seconds
  76. * 9 352 < 0 seconds
  77. * 10 724 < 0 seconds
  78. * 11 2680 < 0 seconds
  79. * 12 14200 < 0 seconds
  80. * 13 73712 < 0 seconds
  81. * 14 365596 00:00:01
  82. * 15 2279184 00:00:04
  83. * 16 14772512 00:00:23
  84. * 17 95815104 00:02:38
  85. * 18 666090624 00:19:26
  86. * 19 4968057848 02:31:24
  87. * 20 39029188884 20:35:06
  88. * 21 314666222712 174:53:45
  89. * 22 2691008701644 ?
  90. * 23 24233937684440 ?
  91. * 24 ? ?
  92. */
  93.  
  94. #include <stdio.h>
  95. #include <stdlib.h>
  96. #include <time.h>
  97.  
  98. /*
  99. Notes on MAX_BOARDSIZE:
  100.  
  101. A 32 bit unsigned long is sufficient to hold the results for an 18 x 18
  102. board (666090624 solutions) but not for a 19 x 19 board (4968057848 solutions).
  103.  
  104. In Win32, I use a 64 bit variable to hold the results, and merely set the
  105. MAX_BOARDSIZE to 21 because that's the largest board for which I've
  106. calculated a result.
  107.  
  108. Note: a 20x20 board will take over 20 hours to run on a Pentium III 800MHz,
  109. while a 21x21 board will take over a week to run on the same PC.
  110.  
  111. On Unix, you could probably change the type of g_numsolutions from unsigned long
  112. to unsigned long long, or change the code to use two 32 bit ints to store the
  113. results for board sizes 19 x 19 and up.
  114. */
  115.  
  116. #ifdef WIN32
  117.  
  118. #define MAX_BOARDSIZE 21
  119. typedef unsigned __int64 SOLUTIONTYPE;
  120.  
  121. #else
  122.  
  123. #define MAX_BOARDSIZE 18
  124. typedef unsigned long SOLUTIONTYPE;
  125.  
  126. #endif
  127.  
  128. #define MIN_BOARDSIZE 2
  129.  
  130. SOLUTIONTYPE g_numsolutions = ;
  131.  
  132. /* Print a chess table with queens positioned for a solution */
  133. /* This is not a critical path function & I didn't try to optimize it. */
  134. void printtable(int boardsize, int* aQueenBitRes, SOLUTIONTYPE numSolution)
  135. {
  136. int i, j, k, row;
  137.  
  138. /* We only calculated half the solutions, because we can derive
  139. the other half by reflecting the solution across the "Y axis". */
  140. for (k = ; k < ; ++k)
  141. {
  142. #ifdef WIN32
  143. printf("*** Solution #: %I64d ***\n", * numSolution + k - );
  144. #else
  145. printf("*** Solution #: %d ***\n", * numSolution + k - );
  146. #endif
  147. for ( i = ; i < boardsize; i++)
  148. {
  149. unsigned int bitf;
  150. /*
  151. Get the column that was set (i.e. find the
  152. first, least significant, bit set).
  153. If aQueenBitRes[i] = 011010b, then
  154. bitf = 000010b
  155. */
  156. bitf = aQueenBitRes[i];
  157.  
  158. row = bitf ^ (bitf & (bitf - )); /* get least significant bit */
  159. for ( j = ; j < boardsize; j++)
  160. {
  161. /* keep shifting row over to the right until we find the one '1' in
  162. the binary representation. There will only be one '1'. */
  163. if ( == k && ((row >> j) & ))
  164. {
  165. printf("Q ");
  166. }
  167. else if ( == k && (row & ( << (boardsize - j - )))) /* this is the board reflected across the "Y axis" */
  168. {
  169. printf("Q ");
  170. }
  171. else
  172. {
  173. printf(". ");
  174. }
  175. }
  176. printf("\n");
  177. }
  178. printf("\n");
  179. }
  180. }
  181.  
  182. /* The function which calculates the N queen solutions.
  183. We calculate one-half the solutions, then flip the results over
  184. the "Y axis" of the board. Every solution can be reflected that
  185. way to generate another unique solution (assuming the board size
  186. isn't 1 x 1). That's because a solution cannot be symmetrical
  187. across the Y-axis (because you can't have two queens in the same
  188. horizontal row). A solution also cannot consist of queens
  189. down the middle column of a board with an odd number of columns,
  190. since you can't have two queens in the same vertical row.
  191.  
  192. This is a backtracking algorithm. We place a queen in the top
  193. row, then note the column and diagonals it occupies. We then
  194. place a queen in the next row down, taking care not to place it
  195. in the same column or diagonal. We then update the occupied
  196. columns & diagonals & move on to the next row. If no position
  197. is open in the next row, we back track to the previous row & move
  198. the queen over to the next available spot in its row & the process
  199. starts over again.
  200. */
  201. void Nqueen(int board_size)
  202. {
  203. int aQueenBitRes[MAX_BOARDSIZE]; /* results */
  204. int aQueenBitCol[MAX_BOARDSIZE]; /* marks colummns which already have queens */
  205. int aQueenBitPosDiag[MAX_BOARDSIZE]; /* marks "positive diagonals" which already have queens */
  206. int aQueenBitNegDiag[MAX_BOARDSIZE]; /* marks "negative diagonals" which already have queens */
  207. int aStack[MAX_BOARDSIZE + ]; /* we use a stack instead of recursion */
  208. register int* pnStack;
  209.  
  210. register int numrows = ; /* numrows redundant - could use stack */
  211. register unsigned int lsb; /* least significant bit */
  212. register unsigned int bitfield; /* bits which are set mark possible positions for a queen */
  213. int i;
  214. int odd = board_size & ; /* 0 if board_size even, 1 if odd */
  215. int board_minus = board_size - ; /* board size - 1 */
  216. int mask = ( << board_size) - ; /* if board size is N, mask consists of N 1's */
  217.  
  218. /* Initialize stack */
  219. aStack[] = -; /* set sentinel -- signifies end of stack */
  220.  
  221. /* NOTE: (board_size & 1) is true iff board_size is odd */
  222. /* We need to loop through 2x if board_size is odd */
  223. for (i = ; i < ( + odd); ++i)
  224. {
  225. /* We don't have to optimize this part; it ain't the
  226. critical loop */
  227. bitfield = ;
  228. if ( == i)
  229. {
  230. /* Handle half of the board, except the middle
  231. column. So if the board is 5 x 5, the first
  232. row will be: 00011, since we're not worrying
  233. about placing a queen in the center column (yet).
  234. */
  235. int half = board_size>>; /* divide by two */
  236. /* fill in rightmost 1's in bitfield for half of board_size
  237. If board_size is 7, half of that is 3 (we're discarding the remainder)
  238. and bitfield will be set to 111 in binary. */
  239. bitfield = ( << half) - ;
  240. pnStack = aStack + ; /* stack pointer */
  241.  
  242. aQueenBitRes[] = ;
  243. aQueenBitCol[] = aQueenBitPosDiag[] = aQueenBitNegDiag[] = ;
  244. }
  245. else
  246. {
  247. /* Handle the middle column (of a odd-sized board).
  248. Set middle column bit to 1, then set
  249. half of next row.
  250. So we're processing first row (one element) & half of next.
  251. So if the board is 5 x 5, the first row will be: 00100, and
  252. the next row will be 00011.
  253. */
  254. bitfield = << (board_size >> );
  255. numrows = ; /* prob. already 0 */
  256.  
  257. /* The first row just has one queen (in the middle column).*/
  258. aQueenBitRes[] = bitfield;
  259. aQueenBitCol[] = aQueenBitPosDiag[] = aQueenBitNegDiag[] = ;
  260. aQueenBitCol[] = bitfield;
  261.  
  262. /* Now do the next row. Only set bits in half of it, because we'll
  263. flip the results over the "Y-axis". */
  264. aQueenBitNegDiag[] = (bitfield >> );
  265. aQueenBitPosDiag[] = (bitfield << );
  266. pnStack = aStack + ; /* stack pointer */
  267. *pnStack++ = ; /* we're done w/ this row -- only 1 element & we've done it */
  268. bitfield = (bitfield - ) >> ; /* bitfield -1 is all 1's to the left of the single 1 */
  269. }
  270.  
  271. /* this is the critical loop */
  272. for (;;)
  273. {
  274. /* could use
  275. lsb = bitfield ^ (bitfield & (bitfield -1));
  276. to get first (least sig) "1" bit, but that's slower. */
  277. lsb = -((signed)bitfield) & bitfield; /* this assumes a 2's complement architecture */
  278. if ( == bitfield)
  279. {
  280. bitfield = *--pnStack; /* get prev. bitfield from stack */
  281. if (pnStack == aStack) { /* if sentinel hit.... */
  282. break ;
  283. }
  284. --numrows;
  285. continue;
  286. }
  287. bitfield &= ~lsb; /* toggle off this bit so we don't try it again */
  288.  
  289. aQueenBitRes[numrows] = lsb; /* save the result */
  290. if (numrows < board_minus) /* we still have more rows to process? */
  291. {
  292. int n = numrows++;
  293. aQueenBitCol[numrows] = aQueenBitCol[n] | lsb;
  294. aQueenBitNegDiag[numrows] = (aQueenBitNegDiag[n] | lsb) >> ;
  295. aQueenBitPosDiag[numrows] = (aQueenBitPosDiag[n] | lsb) << ;
  296. *pnStack++ = bitfield;
  297. /* We can't consider positions for the queen which are in the same
  298. column, same positive diagonal, or same negative diagonal as another
  299. queen already on the board. */
  300. bitfield = mask & ~(aQueenBitCol[numrows] | aQueenBitNegDiag[numrows] | aQueenBitPosDiag[numrows]);
  301. continue;
  302. }
  303. else
  304. {
  305. /* We have no more rows to process; we found a solution. */
  306. /* Comment out the call to printtable in order to print the solutions as board position*/
  307. /* printtable(board_size, aQueenBitRes, g_numsolutions + 1); */
  308. ++g_numsolutions;
  309. bitfield = *--pnStack;
  310. --numrows;
  311. continue;
  312. }
  313. }
  314. }
  315.  
  316. /* multiply solutions by two, to count mirror images */
  317. g_numsolutions *= ;
  318. }
  319.  
  320. /* Print the results at the end of the run */
  321. void printResults(time_t* pt1, time_t* pt2)
  322. {
  323. double secs;
  324. int hours , mins, intsecs;
  325.  
  326. printf("End: \t%s", ctime(pt2));
  327. secs = difftime(*pt2, *pt1);
  328. intsecs = (int)secs;
  329. printf("Calculations took %d second%s.\n", intsecs, (intsecs == ? "" : "s"));
  330.  
  331. /* Print hours, minutes, seconds */
  332. hours = intsecs/;
  333. intsecs -= hours * ;
  334. mins = intsecs/;
  335. intsecs -= mins * ;
  336. if (hours > || mins > )
  337. {
  338. printf("Equals ");
  339. if (hours > )
  340. {
  341. printf("%d hour%s, ", hours, (hours == ) ? "" : "s");
  342. }
  343. if (mins > )
  344. {
  345. printf("%d minute%s and ", mins, (mins == ) ? "" : "s");
  346. }
  347. printf("%d second%s.\n", intsecs, (intsecs == ? "" : "s"));
  348.  
  349. }
  350. }
  351.  
  352. /* main routine for N Queens program.*/
  353. int main(int argc, char** argv)
  354. {
  355. time_t t1, t2;
  356. int boardsize;
  357.  
  358. if (argc != ) {
  359. printf("N Queens program by Jeff Somers.\n");
  360. printf("\tallagash98@yahoo.com or jsomers@alumni.williams.edu\n");
  361. printf("This program calculates the total number of solutions to the N Queens problem.\n");
  362. printf("Usage: nq <width of board>\n"); /* user must pass in size of board */
  363. return ;
  364. }
  365.  
  366. boardsize = atoi(argv[]);
  367.  
  368. /* check size of board is within correct range */
  369. if (MIN_BOARDSIZE > boardsize || MAX_BOARDSIZE < boardsize)
  370. {
  371. printf("Width of board must be between %d and %d, inclusive.\n",
  372. MIN_BOARDSIZE, MAX_BOARDSIZE );
  373. return ;
  374. }
  375.  
  376. time(&t1);
  377. printf("N Queens program by Jeff Somers.\n");
  378. printf("\tallagash98@yahoo.com or jsomers@alumni.williams.edu\n");
  379. printf("Start: \t %s", ctime(&t1));
  380.  
  381. Nqueen(boardsize); /* find solutions */
  382. time(&t2);
  383.  
  384. printResults(&t1, &t2);
  385.  
  386. if (g_numsolutions != )
  387. {
  388. #ifdef WIN32
  389. printf("For board size %d, %I64d solution%s found.\n", boardsize, g_numsolutions, (g_numsolutions == ? "" : "s"));
  390. #else
  391. printf("For board size %d, %d solution%s found.\n", boardsize, g_numsolutions, (g_numsolutions == ? "" : "s"));
  392. #endif
  393. }
  394. else
  395. {
  396. printf("No solutions found.\n");
  397. }
  398.  
  399. return ;
  400. }

Jeff Somers's N Queens Solutions 最快的n皇后算法的更多相关文章

  1. 最快的Hash表算法

    我们由一个简单的问题逐步入手:有一个庞大的字符串数组,然后给你一个单独的字符串,让你从这个数组中查找是否有这个字符串并找到它,你会怎么做?有一个方法最简单,老老实实从头查到尾,一个一个比较,直到找到为 ...

  2. 荷兰国旗问题、快排以及BFPRT算法

    荷兰国旗问题 给定一个数组arr,和一个数num,请把小于num的数放数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边.要求额外空间复杂度O(1),时间复杂度O(N). 这个问题 ...

  3. 【算法】N Queens Problem

    /* ** 目前最快的N皇后递归解决方法 ** N Queens Problem ** 试探-回溯算法,递归实现 */ #include "stdafx.h" #include & ...

  4. Jeff Dean 光辉事迹

    这是Google 2007年的愚人节笑话,罗列了很多Jeff Dean的“光辉事迹”.大名鼎鼎的Jeff Dean想必不用我介绍了.……好吧,还是介绍一下,Jeff Dean是Google最早的一批员 ...

  5. 排序 之 快排、归并、插入 - <时间复杂度>----掌握思想和过程

    俗话说:天下武功无坚不破,唯快不破.对于算法当然也是要使用时间最短.占用空间最小的算法来实现了. 注意:我代码里面打的备注仅供参考,建议不要背模板(因为没有固定的模板),可以写一个数列按着代码跑两圈或 ...

  6. 嫌弃Apriori算法太慢?使用FP-growth算法让你的数据挖掘快到飞起

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是机器学习专题的第20篇文章,我们来看看FP-growth算法. 这个算法挺冷门的,至少比Apriori算法冷门.很多数据挖掘的教材还会 ...

  7. 利用共享内存实现比NCCL更快的集合通信

    作者:曹彬 | 旷视 MegEngine 架构师 简介 从 2080Ti 这一代显卡开始,所有的民用游戏卡都取消了 P2P copy,导致训练速度显著的变慢.针对这种情况下的单机多卡训练,MegEng ...

  8. 计算机网络传输层之TCP拥塞控制(慢开始与拥塞避免、快重传和快恢复)

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105532044 学习课程:<2019王道考研计算机网络> 学习目的 ...

  9. 快Key:按一下鼠标【滚轮】,帮你自动填写用户名密码,快速登录,可制作U盘随身(开源免费-附安装文件和源代码)

    * 代码以本文所附下载文件包为准,安装文件和源文件包均在本文尾部可下载. * 快Key及本文所有内容仅供交流使用,使用者责任自负,由快Key对使用者及其相关人员或组织造成的任何损失均由使用者自负,与本 ...

随机推荐

  1. nginx重定向规则入门

    nginx重定向规则的入门实例 时间:2015-12-17 15:18:03来源:网络 导读:nginx重定向规则,Nginx的重定向模块HttpRewriteModule的用法说明,nginx重定向 ...

  2. NoSql---MongoDB基本操作

    MongoDB 最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语 言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引.最后由于 MongoDB 可以支 ...

  3. Win10系统下编译GDAL1.9.2版本

    环境说明: 1.Win10企业版.64位: 2.VS2012旗舰版: 3.GDAL1.9.2 GADL编译 1.解压GDAL压缩包至F:\GDAL\gdal-1.9.2: 2.设置GDAL编译后安装目 ...

  4. 在server 2008/2003中 取消对网站的安全检查/去除添加信任网站

    新安装好Windows   Server   2003操作系统后,打开浏览器来查询网上信息时,发现IE总是“不厌其烦”地提示我们,是否需要将当前访问的网站添加到自己信任的站点中去:要是不信任的话,就无 ...

  5. 简约而不简单:网站着陆页的设计(Landing Page Design)

    着陆页是一个在线营销的概念,是指当访客点击一个搜索引擎优化的搜索结果进入的第一个页面或“着陆”页面.这是一个重要的页面,它和提供的产品或服务的广告有点类似,提供了与产品相关的精确的信息,告诉客户可以购 ...

  6. Sapi 添加语法的文章(转载)

    最近在做SAPI方面的工作,比较详细的中文资料不多,遇到各种问题,本来想着做完了项目总结一下,今天看到这篇文章,对于SAPI加载识别语法方面的描述十分详细,先转过来做个备份,谢谢原文博主:djyang ...

  7. python第三方模块精选

    python不但有着强大丰富的“内置电池”,同样的,第三方模块也是非常的多.目前收集了requests.paramiko.pymsql,以后会陆续添加: 一.requests Python标准库中提供 ...

  8. [Solution] AOP原理解析及Castle、Autofac、Unity框架使用

    本节目录: AOP介绍 AOP基本原理 AOP框架 Castle Core Castle Windsor Autofac Unity AOP介绍 面向切面编程(Aspect Oriented Prog ...

  9. [Tool] Visual Studio必备插件 + 技能

    总结自己常用的VS插件,其中部分需要注册. 在该链接http://www.cnblogs.com/neverc/p/4591501.html中提供 1.Web Essentials(测试支持2010, ...

  10. 存储过程分页 Ado.Net分页 EF分页 满足90%以上

    存储过程分页: create proc PR_PagerDataByTop @pageIndex int, @pageSize int, @count int out as select top(@p ...