Jeff Somers's N Queens Solutions 最快的n皇后算法
- /* Jeff Somers
- *
- * Copyright (c) 2002
- *
- * jsomers@alumni.williams.edu
- * or
- * allagash98@yahoo.com
- *
- * April, 2002
- *
- * Program: nq
- *
- * Program to find number of solutions to the N queens problem.
- * This program assumes a twos complement architecture.
- *
- * For example, you can arrange 4 queens on 4 x 4 chess so that
- * none of the queens can attack each other:
- *
- * Two solutions:
- * _ Q _ _ _ _ Q _
- * _ _ _ Q Q _ _ _
- * Q _ _ _ _ _ _ Q
- * _ _ Q _ and _ Q _ _
- *
- * Note that these are separate solutions, even though they
- * are mirror images of each other.
- *
- * Likewise, a 8 x 8 chess board has 92 solutions to the 8 queens
- * problem.
- *
- * Command Line Usage:
- *
- * nq N
- *
- * where N is the size of the N x N board. For example,
- * nq 4 will find the 4 queen solution for the 4 x 4 chess
- * board.
- *
- * By default, this program will only print the number of solutions,
- * not board arrangements which are the solutions. To print the
- * boards, uncomment the call to printtable in the Nqueen function.
- * Note that printing the board arrangements slows down the program
- * quite a bit, unless you pipe the output to a text file:
- *
- * nq 10 > output.txt
- *
- *
- * The number of solutions for the N queens problems are known for
- * boards up to 23 x 23. With this program, I've calculated the
- * results for boards up to 21 x 21, and that took over a week on
- * an 800 MHz PC. The algorithm is approximated O(n!) (i.e. slow),
- * and calculating the results for a 22 x 22 board will take about 8.5
- * times the amount of time for the 21 x 21 board, or over 8 1/2 weeks.
- * Even with a 10 GHz machine, calculating the results for a 23 x 23
- * board would take over a month. Of course, setting up a cluster of
- * machines (or a distributed client) would do the work in less time.
- *
- * (from Sloane's On-Line Encyclopedia of Integer Sequences,
- * Sequence A000170
- * http://www.research.att.com/cgi-bin/access.cgi/as/njas/sequences/eisA.cgi?Anum=000170
- * )
- *
- * Board Size: Number of Solutions to Time to calculate
- * (length of one N queens problem: on 800MHz PC
- * side of N x N (Hours:Mins:Secs)
- * chessboard)
- *
- * 1 1 n/a
- * 2 0 < 0 seconds
- * 3 0 < 0 seconds
- * 4 2 < 0 seconds
- * 5 10 < 0 seconds
- * 6 4 < 0 seconds
- * 7 40 < 0 seconds
- * 8 92 < 0 seconds
- * 9 352 < 0 seconds
- * 10 724 < 0 seconds
- * 11 2680 < 0 seconds
- * 12 14200 < 0 seconds
- * 13 73712 < 0 seconds
- * 14 365596 00:00:01
- * 15 2279184 00:00:04
- * 16 14772512 00:00:23
- * 17 95815104 00:02:38
- * 18 666090624 00:19:26
- * 19 4968057848 02:31:24
- * 20 39029188884 20:35:06
- * 21 314666222712 174:53:45
- * 22 2691008701644 ?
- * 23 24233937684440 ?
- * 24 ? ?
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- /*
- Notes on MAX_BOARDSIZE:
- A 32 bit unsigned long is sufficient to hold the results for an 18 x 18
- board (666090624 solutions) but not for a 19 x 19 board (4968057848 solutions).
- In Win32, I use a 64 bit variable to hold the results, and merely set the
- MAX_BOARDSIZE to 21 because that's the largest board for which I've
- calculated a result.
- Note: a 20x20 board will take over 20 hours to run on a Pentium III 800MHz,
- while a 21x21 board will take over a week to run on the same PC.
- On Unix, you could probably change the type of g_numsolutions from unsigned long
- to unsigned long long, or change the code to use two 32 bit ints to store the
- results for board sizes 19 x 19 and up.
- */
- #ifdef WIN32
- #define MAX_BOARDSIZE 21
- typedef unsigned __int64 SOLUTIONTYPE;
- #else
- #define MAX_BOARDSIZE 18
- typedef unsigned long SOLUTIONTYPE;
- #endif
- #define MIN_BOARDSIZE 2
- SOLUTIONTYPE g_numsolutions = ;
- /* Print a chess table with queens positioned for a solution */
- /* This is not a critical path function & I didn't try to optimize it. */
- void printtable(int boardsize, int* aQueenBitRes, SOLUTIONTYPE numSolution)
- {
- int i, j, k, row;
- /* We only calculated half the solutions, because we can derive
- the other half by reflecting the solution across the "Y axis". */
- for (k = ; k < ; ++k)
- {
- #ifdef WIN32
- printf("*** Solution #: %I64d ***\n", * numSolution + k - );
- #else
- printf("*** Solution #: %d ***\n", * numSolution + k - );
- #endif
- for ( i = ; i < boardsize; i++)
- {
- unsigned int bitf;
- /*
- Get the column that was set (i.e. find the
- first, least significant, bit set).
- If aQueenBitRes[i] = 011010b, then
- bitf = 000010b
- */
- bitf = aQueenBitRes[i];
- row = bitf ^ (bitf & (bitf - )); /* get least significant bit */
- for ( j = ; j < boardsize; j++)
- {
- /* keep shifting row over to the right until we find the one '1' in
- the binary representation. There will only be one '1'. */
- if ( == k && ((row >> j) & ))
- {
- printf("Q ");
- }
- else if ( == k && (row & ( << (boardsize - j - )))) /* this is the board reflected across the "Y axis" */
- {
- printf("Q ");
- }
- else
- {
- printf(". ");
- }
- }
- printf("\n");
- }
- printf("\n");
- }
- }
- /* The function which calculates the N queen solutions.
- We calculate one-half the solutions, then flip the results over
- the "Y axis" of the board. Every solution can be reflected that
- way to generate another unique solution (assuming the board size
- isn't 1 x 1). That's because a solution cannot be symmetrical
- across the Y-axis (because you can't have two queens in the same
- horizontal row). A solution also cannot consist of queens
- down the middle column of a board with an odd number of columns,
- since you can't have two queens in the same vertical row.
- This is a backtracking algorithm. We place a queen in the top
- row, then note the column and diagonals it occupies. We then
- place a queen in the next row down, taking care not to place it
- in the same column or diagonal. We then update the occupied
- columns & diagonals & move on to the next row. If no position
- is open in the next row, we back track to the previous row & move
- the queen over to the next available spot in its row & the process
- starts over again.
- */
- void Nqueen(int board_size)
- {
- int aQueenBitRes[MAX_BOARDSIZE]; /* results */
- int aQueenBitCol[MAX_BOARDSIZE]; /* marks colummns which already have queens */
- int aQueenBitPosDiag[MAX_BOARDSIZE]; /* marks "positive diagonals" which already have queens */
- int aQueenBitNegDiag[MAX_BOARDSIZE]; /* marks "negative diagonals" which already have queens */
- int aStack[MAX_BOARDSIZE + ]; /* we use a stack instead of recursion */
- register int* pnStack;
- register int numrows = ; /* numrows redundant - could use stack */
- register unsigned int lsb; /* least significant bit */
- register unsigned int bitfield; /* bits which are set mark possible positions for a queen */
- int i;
- int odd = board_size & ; /* 0 if board_size even, 1 if odd */
- int board_minus = board_size - ; /* board size - 1 */
- int mask = ( << board_size) - ; /* if board size is N, mask consists of N 1's */
- /* Initialize stack */
- aStack[] = -; /* set sentinel -- signifies end of stack */
- /* NOTE: (board_size & 1) is true iff board_size is odd */
- /* We need to loop through 2x if board_size is odd */
- for (i = ; i < ( + odd); ++i)
- {
- /* We don't have to optimize this part; it ain't the
- critical loop */
- bitfield = ;
- if ( == i)
- {
- /* Handle half of the board, except the middle
- column. So if the board is 5 x 5, the first
- row will be: 00011, since we're not worrying
- about placing a queen in the center column (yet).
- */
- int half = board_size>>; /* divide by two */
- /* fill in rightmost 1's in bitfield for half of board_size
- If board_size is 7, half of that is 3 (we're discarding the remainder)
- and bitfield will be set to 111 in binary. */
- bitfield = ( << half) - ;
- pnStack = aStack + ; /* stack pointer */
- aQueenBitRes[] = ;
- aQueenBitCol[] = aQueenBitPosDiag[] = aQueenBitNegDiag[] = ;
- }
- else
- {
- /* Handle the middle column (of a odd-sized board).
- Set middle column bit to 1, then set
- half of next row.
- So we're processing first row (one element) & half of next.
- So if the board is 5 x 5, the first row will be: 00100, and
- the next row will be 00011.
- */
- bitfield = << (board_size >> );
- numrows = ; /* prob. already 0 */
- /* The first row just has one queen (in the middle column).*/
- aQueenBitRes[] = bitfield;
- aQueenBitCol[] = aQueenBitPosDiag[] = aQueenBitNegDiag[] = ;
- aQueenBitCol[] = bitfield;
- /* Now do the next row. Only set bits in half of it, because we'll
- flip the results over the "Y-axis". */
- aQueenBitNegDiag[] = (bitfield >> );
- aQueenBitPosDiag[] = (bitfield << );
- pnStack = aStack + ; /* stack pointer */
- *pnStack++ = ; /* we're done w/ this row -- only 1 element & we've done it */
- bitfield = (bitfield - ) >> ; /* bitfield -1 is all 1's to the left of the single 1 */
- }
- /* this is the critical loop */
- for (;;)
- {
- /* could use
- lsb = bitfield ^ (bitfield & (bitfield -1));
- to get first (least sig) "1" bit, but that's slower. */
- lsb = -((signed)bitfield) & bitfield; /* this assumes a 2's complement architecture */
- if ( == bitfield)
- {
- bitfield = *--pnStack; /* get prev. bitfield from stack */
- if (pnStack == aStack) { /* if sentinel hit.... */
- break ;
- }
- --numrows;
- continue;
- }
- bitfield &= ~lsb; /* toggle off this bit so we don't try it again */
- aQueenBitRes[numrows] = lsb; /* save the result */
- if (numrows < board_minus) /* we still have more rows to process? */
- {
- int n = numrows++;
- aQueenBitCol[numrows] = aQueenBitCol[n] | lsb;
- aQueenBitNegDiag[numrows] = (aQueenBitNegDiag[n] | lsb) >> ;
- aQueenBitPosDiag[numrows] = (aQueenBitPosDiag[n] | lsb) << ;
- *pnStack++ = bitfield;
- /* We can't consider positions for the queen which are in the same
- column, same positive diagonal, or same negative diagonal as another
- queen already on the board. */
- bitfield = mask & ~(aQueenBitCol[numrows] | aQueenBitNegDiag[numrows] | aQueenBitPosDiag[numrows]);
- continue;
- }
- else
- {
- /* We have no more rows to process; we found a solution. */
- /* Comment out the call to printtable in order to print the solutions as board position*/
- /* printtable(board_size, aQueenBitRes, g_numsolutions + 1); */
- ++g_numsolutions;
- bitfield = *--pnStack;
- --numrows;
- continue;
- }
- }
- }
- /* multiply solutions by two, to count mirror images */
- g_numsolutions *= ;
- }
- /* Print the results at the end of the run */
- void printResults(time_t* pt1, time_t* pt2)
- {
- double secs;
- int hours , mins, intsecs;
- printf("End: \t%s", ctime(pt2));
- secs = difftime(*pt2, *pt1);
- intsecs = (int)secs;
- printf("Calculations took %d second%s.\n", intsecs, (intsecs == ? "" : "s"));
- /* Print hours, minutes, seconds */
- hours = intsecs/;
- intsecs -= hours * ;
- mins = intsecs/;
- intsecs -= mins * ;
- if (hours > || mins > )
- {
- printf("Equals ");
- if (hours > )
- {
- printf("%d hour%s, ", hours, (hours == ) ? "" : "s");
- }
- if (mins > )
- {
- printf("%d minute%s and ", mins, (mins == ) ? "" : "s");
- }
- printf("%d second%s.\n", intsecs, (intsecs == ? "" : "s"));
- }
- }
- /* main routine for N Queens program.*/
- int main(int argc, char** argv)
- {
- time_t t1, t2;
- int boardsize;
- if (argc != ) {
- printf("N Queens program by Jeff Somers.\n");
- printf("\tallagash98@yahoo.com or jsomers@alumni.williams.edu\n");
- printf("This program calculates the total number of solutions to the N Queens problem.\n");
- printf("Usage: nq <width of board>\n"); /* user must pass in size of board */
- return ;
- }
- boardsize = atoi(argv[]);
- /* check size of board is within correct range */
- if (MIN_BOARDSIZE > boardsize || MAX_BOARDSIZE < boardsize)
- {
- printf("Width of board must be between %d and %d, inclusive.\n",
- MIN_BOARDSIZE, MAX_BOARDSIZE );
- return ;
- }
- time(&t1);
- printf("N Queens program by Jeff Somers.\n");
- printf("\tallagash98@yahoo.com or jsomers@alumni.williams.edu\n");
- printf("Start: \t %s", ctime(&t1));
- Nqueen(boardsize); /* find solutions */
- time(&t2);
- printResults(&t1, &t2);
- if (g_numsolutions != )
- {
- #ifdef WIN32
- printf("For board size %d, %I64d solution%s found.\n", boardsize, g_numsolutions, (g_numsolutions == ? "" : "s"));
- #else
- printf("For board size %d, %d solution%s found.\n", boardsize, g_numsolutions, (g_numsolutions == ? "" : "s"));
- #endif
- }
- else
- {
- printf("No solutions found.\n");
- }
- return ;
- }
Jeff Somers's N Queens Solutions 最快的n皇后算法的更多相关文章
- 最快的Hash表算法
我们由一个简单的问题逐步入手:有一个庞大的字符串数组,然后给你一个单独的字符串,让你从这个数组中查找是否有这个字符串并找到它,你会怎么做?有一个方法最简单,老老实实从头查到尾,一个一个比较,直到找到为 ...
- 荷兰国旗问题、快排以及BFPRT算法
荷兰国旗问题 给定一个数组arr,和一个数num,请把小于num的数放数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边.要求额外空间复杂度O(1),时间复杂度O(N). 这个问题 ...
- 【算法】N Queens Problem
/* ** 目前最快的N皇后递归解决方法 ** N Queens Problem ** 试探-回溯算法,递归实现 */ #include "stdafx.h" #include & ...
- Jeff Dean 光辉事迹
这是Google 2007年的愚人节笑话,罗列了很多Jeff Dean的“光辉事迹”.大名鼎鼎的Jeff Dean想必不用我介绍了.……好吧,还是介绍一下,Jeff Dean是Google最早的一批员 ...
- 排序 之 快排、归并、插入 - <时间复杂度>----掌握思想和过程
俗话说:天下武功无坚不破,唯快不破.对于算法当然也是要使用时间最短.占用空间最小的算法来实现了. 注意:我代码里面打的备注仅供参考,建议不要背模板(因为没有固定的模板),可以写一个数列按着代码跑两圈或 ...
- 嫌弃Apriori算法太慢?使用FP-growth算法让你的数据挖掘快到飞起
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是机器学习专题的第20篇文章,我们来看看FP-growth算法. 这个算法挺冷门的,至少比Apriori算法冷门.很多数据挖掘的教材还会 ...
- 利用共享内存实现比NCCL更快的集合通信
作者:曹彬 | 旷视 MegEngine 架构师 简介 从 2080Ti 这一代显卡开始,所有的民用游戏卡都取消了 P2P copy,导致训练速度显著的变慢.针对这种情况下的单机多卡训练,MegEng ...
- 计算机网络传输层之TCP拥塞控制(慢开始与拥塞避免、快重传和快恢复)
文章转自:https://blog.csdn.net/weixin_43914604/article/details/105532044 学习课程:<2019王道考研计算机网络> 学习目的 ...
- 快Key:按一下鼠标【滚轮】,帮你自动填写用户名密码,快速登录,可制作U盘随身(开源免费-附安装文件和源代码)
* 代码以本文所附下载文件包为准,安装文件和源文件包均在本文尾部可下载. * 快Key及本文所有内容仅供交流使用,使用者责任自负,由快Key对使用者及其相关人员或组织造成的任何损失均由使用者自负,与本 ...
随机推荐
- nginx重定向规则入门
nginx重定向规则的入门实例 时间:2015-12-17 15:18:03来源:网络 导读:nginx重定向规则,Nginx的重定向模块HttpRewriteModule的用法说明,nginx重定向 ...
- NoSql---MongoDB基本操作
MongoDB 最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语 言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引.最后由于 MongoDB 可以支 ...
- Win10系统下编译GDAL1.9.2版本
环境说明: 1.Win10企业版.64位: 2.VS2012旗舰版: 3.GDAL1.9.2 GADL编译 1.解压GDAL压缩包至F:\GDAL\gdal-1.9.2: 2.设置GDAL编译后安装目 ...
- 在server 2008/2003中 取消对网站的安全检查/去除添加信任网站
新安装好Windows Server 2003操作系统后,打开浏览器来查询网上信息时,发现IE总是“不厌其烦”地提示我们,是否需要将当前访问的网站添加到自己信任的站点中去:要是不信任的话,就无 ...
- 简约而不简单:网站着陆页的设计(Landing Page Design)
着陆页是一个在线营销的概念,是指当访客点击一个搜索引擎优化的搜索结果进入的第一个页面或“着陆”页面.这是一个重要的页面,它和提供的产品或服务的广告有点类似,提供了与产品相关的精确的信息,告诉客户可以购 ...
- Sapi 添加语法的文章(转载)
最近在做SAPI方面的工作,比较详细的中文资料不多,遇到各种问题,本来想着做完了项目总结一下,今天看到这篇文章,对于SAPI加载识别语法方面的描述十分详细,先转过来做个备份,谢谢原文博主:djyang ...
- python第三方模块精选
python不但有着强大丰富的“内置电池”,同样的,第三方模块也是非常的多.目前收集了requests.paramiko.pymsql,以后会陆续添加: 一.requests Python标准库中提供 ...
- [Solution] AOP原理解析及Castle、Autofac、Unity框架使用
本节目录: AOP介绍 AOP基本原理 AOP框架 Castle Core Castle Windsor Autofac Unity AOP介绍 面向切面编程(Aspect Oriented Prog ...
- [Tool] Visual Studio必备插件 + 技能
总结自己常用的VS插件,其中部分需要注册. 在该链接http://www.cnblogs.com/neverc/p/4591501.html中提供 1.Web Essentials(测试支持2010, ...
- 存储过程分页 Ado.Net分页 EF分页 满足90%以上
存储过程分页: create proc PR_PagerDataByTop @pageIndex int, @pageSize int, @count int out as select top(@p ...