【转载】数学游戏(mathgame)解题方法 - N皇后位运算解法,14皇后亦在1秒中
2016-08-08 09:31
357 查看
【转】桐桐的数学游戏(mathgame)
【问题描述】
相信大家都听过经典的“八皇后”问题吧?这个游戏要求在一个8×8的棋盘上放置8个皇后,使8个皇后互相不攻击(攻击的含义是有两个皇后在同一行或同一列或同一对角线上)。
桐桐对这个游戏很感兴趣,也很快解决了这个问题。可是,他想为自己增加一点难度,于是他想求出n皇后的解的情况。你能帮助他吗?
【输入格式】
输入仅有一个数n(1≤n≤13),表示为n皇后问题。
【输出格式】
输出仅有一个数,表示n皇后时问题的解法总数。
【输入样例】
8
【输出样例】
92
这道问题想必也是非常经典的回朔问题了,但是到现在仍有不少人研究它。我在网上顺路寻找位运算的时候,找到了小时后大概五年级左右非常喜欢的一本书的作者Matrix67的一篇文章,现贴出链接如下:
感谢Matrix67大神!这一程序异常高效
本程序已在GCC 4.9.2 下编译通过,并已经AC本道例题
*/
#define _DUBUG
#include <cstdio>
using namespace std;
int upperlim;
unsigned long long int sum;
void NQueen(int row,int ld,int rd)
{
int pos,p;
if (row!=upperlim)
{
pos=upperlim & ~ (row | ld | rd); //对角线上的用过就禁止。。。。。。
while(pos!=0) //这个循环的循环次数应该是pos中1的个数
{
p=pos & -pos; //相当于取pos二进制位最后一个1
pos=pos-p; //用过了
NQueen(row+p,(ld+p)<<1,(rd+p)>>1); //标记不能用的列,斜线上不能用的位置向左/右移动
}
}
else
{
++sum;
}
}
int main()
{
#ifndef _DEBUG
freopen("mathgame.in","r",stdin);
freopen("mathgame.out","w",stdout);
#endif
int n;
scanf("%d",&n);
upperlim=(1<<n)-1; //upperlim=(2^n)-1
sum=0;
NQueen(0,0,0);
printf("%d\n",sum);
}
像这样的样例程序,进一步的展示出了位运算的高效。当然,这个程序实际上思路也不难。大概就是首先如从第一行开始,第一行的所有位置依次枚举,而在枚举中造成了一些所谓的”禁位“,也就是再放下去会与已知的皇后冲突的地方。第二行就不能和第一行冲突,但显然不用考虑第三行,只用考虑该行上既不是与皇后1同列,也不在其两条对角线之一上的位置,并继续枚举这些可用位置。这,就是这个神奇程序的思想。
【问题描述】
相信大家都听过经典的“八皇后”问题吧?这个游戏要求在一个8×8的棋盘上放置8个皇后,使8个皇后互相不攻击(攻击的含义是有两个皇后在同一行或同一列或同一对角线上)。
桐桐对这个游戏很感兴趣,也很快解决了这个问题。可是,他想为自己增加一点难度,于是他想求出n皇后的解的情况。你能帮助他吗?
【输入格式】
输入仅有一个数n(1≤n≤13),表示为n皇后问题。
【输出格式】
输出仅有一个数,表示n皇后时问题的解法总数。
【输入样例】
8
【输出样例】
92
这道问题想必也是非常经典的回朔问题了,但是到现在仍有不少人研究它。我在网上顺路寻找位运算的时候,找到了小时后大概五年级左右非常喜欢的一本书的作者Matrix67的一篇文章,现贴出链接如下:
位运算简介及实用技巧(一):基础篇: http://www.matrix67.com/blog/archives/263
位运算简介及实用技巧(二):进阶篇(1): http://www.matrix67.com/blog/archives/264
位运算简介及实用技巧(三):进阶篇(2): http://www.matrix67.com/blog/archives/266
位运算简介及实用技巧(四):实战篇: http://www.matrix67.com/blog/archives/268
其中,关于本题解法的程序在(三)里面,试了一下,真的很厉害!连例程都不能比它好,而打表有时也比这还慢一点。亲自测试,发现13只用0.08秒左右,而14只用0.6秒,15只用2.8秒,是我见过的里面最快的。下面给出这位大神的程序(注:从Pascal翻译为C++,使用了GNU风格的缩进,请不要在意)/* 本程序翻译自Matrix67的博客上的Pascal程序,地址为:http://www.matrix67.com/blog/archives/266感谢Matrix67大神!这一程序异常高效
本程序已在GCC 4.9.2 下编译通过,并已经AC本道例题
*/
#define _DUBUG
#include <cstdio>
using namespace std;
int upperlim;
unsigned long long int sum;
void NQueen(int row,int ld,int rd)
{
int pos,p;
if (row!=upperlim)
{
pos=upperlim & ~ (row | ld | rd); //对角线上的用过就禁止。。。。。。
while(pos!=0) //这个循环的循环次数应该是pos中1的个数
{
p=pos & -pos; //相当于取pos二进制位最后一个1
pos=pos-p; //用过了
NQueen(row+p,(ld+p)<<1,(rd+p)>>1); //标记不能用的列,斜线上不能用的位置向左/右移动
}
}
else
{
++sum;
}
}
int main()
{
#ifndef _DEBUG
freopen("mathgame.in","r",stdin);
freopen("mathgame.out","w",stdout);
#endif
int n;
scanf("%d",&n);
upperlim=(1<<n)-1; //upperlim=(2^n)-1
sum=0;
NQueen(0,0,0);
printf("%d\n",sum);
}
像这样的样例程序,进一步的展示出了位运算的高效。当然,这个程序实际上思路也不难。大概就是首先如从第一行开始,第一行的所有位置依次枚举,而在枚举中造成了一些所谓的”禁位“,也就是再放下去会与已知的皇后冲突的地方。第二行就不能和第一行冲突,但显然不用考虑第三行,只用考虑该行上既不是与皇后1同列,也不在其两条对角线之一上的位置,并继续枚举这些可用位置。这,就是这个神奇程序的思想。
相关文章推荐
- 数学游戏(mathgame)解题方法 - N皇后位运算解法,14皇后亦在1秒中
- 数学运算解题方法之时钟问题——找准路程、时间和速度
- 数学与程序的结合——一道游戏题目的快速解法
- (转载)Darkwatch开发游戏使用Scrum方法
- [转载]数学之美番外篇:平凡而又神奇的贝叶斯方法
- 【算法学习笔记】14.暴力求解法02 子集生成的三种方法
- 游戏开发中的一些基本方法(转载)
- 数学的内容、方法和意义(转载)
- 【转载】数学之美番外篇:平凡而又神奇的贝叶斯方法
- JS浮点数相乘运算解决误差的方法 转载
- 【算法学习笔记】14.暴力求解法03 回溯法01 N皇后和素数环
- 14招教你保护路由器安全的方法(转载)
- 学习笔记——shell中进行数学运算的方法
- [转载]等角(斜45度)游戏与数学
- 【转载】解决繁体、日文游戏乱码的五种方法 转载自:http://tieba.baidu.com/p/488627981
- [转载] 约瑟夫问题的数学方法(O(n))
- 求约瑟夫环问题最后胜利者的一般解法以及数学推导方法
- 24点游戏改进版---支持出题,解题运算
- CS 转载:数学之美番外篇:平凡而又神奇的贝叶斯方法