HDU N皇后——高效方法详解(bit方法)
2010-12-21 10:47
357 查看
N皇后的问题是回溯中一个非常非常经典的例子,但是一般大家都是按普通方法去回溯搜索,在14皇后或更大的皇后数时,那种方法耗时太大。这边向大家提供一个高效的算法,通过位运算来实现N皇后~
// 试探-回溯算法,递归实现
//sum用来记录皇后放置成功的不同布局数;upperlim用来标记所有列都已经放置好了皇后。
#include<stdio.h>
#include<stdlib.h>
long sum = 0, upperlim = 1; // 试探算法从最右边的列开始。
void test(long row, long ld, long rd)
{
if (row != upperlim)
{
/* row,ld,rd进行“或”运算,求得所有可以放置皇后的列,对应位为0,
然后再取反后“与”上全1的数,来求得当前所有可以放置皇后的位置,对应列改为1。
也就是求取当前哪些列可以放置皇后。*/
long pos = upperlim & ~(row | ld | rd);
while (pos) // 0 -- 皇后没有地方可放,回溯。
{
// 拷贝pos最右边为1的bit,其余bit置0,也就是取得可以放皇后的最右边的列。
long p = pos & -pos; /*将pos最右边为1的bit清零,也就是为获取下一次
的最右可用列使用做准备,程序将来会回溯到这个位置继续试探。*/
pos -= p; /*row + p,将当前列置1,表示记录这次皇后放置的列。
(ld + p) << 1,标记当前皇后左边相邻的列不允许下一个皇后放置。
(ld + p) >> 1,标记当前皇后右边相邻的列不允许下一个皇后放置。
此处的移位操作实际上是记录对角线上的限制,只是因为问题都化归
到一行网格上来解决,所以表示为列的限制就可以了。显然,随着移位
在每次选择列之前进行,原来N×N网格中某个已放置的皇后针对其对角线
上产生的限制都被记录下来了。 */
test(row + p, (ld + p) << 1, (rd + p) >> 1);
}
}
else
{
// row的所有位都为1,即找到了一个成功的布局,回溯。
sum++;
}
}
int main()
{
time_t tm;
int n;
while(scanf("%d",&n)&&n!=0)
{
upperlim=1;
sum=0;
upperlim = (upperlim << n) - 1; /*即upperlim=2^n-1(2的n次方减1),
使得低n位都为1,其余位都为0*/
test(0, 0, 0);
printf("%ld/n",sum);
}
system("pause");
return 0;
}
// 试探-回溯算法,递归实现
//sum用来记录皇后放置成功的不同布局数;upperlim用来标记所有列都已经放置好了皇后。
#include<stdio.h>
#include<stdlib.h>
long sum = 0, upperlim = 1; // 试探算法从最右边的列开始。
void test(long row, long ld, long rd)
{
if (row != upperlim)
{
/* row,ld,rd进行“或”运算,求得所有可以放置皇后的列,对应位为0,
然后再取反后“与”上全1的数,来求得当前所有可以放置皇后的位置,对应列改为1。
也就是求取当前哪些列可以放置皇后。*/
long pos = upperlim & ~(row | ld | rd);
while (pos) // 0 -- 皇后没有地方可放,回溯。
{
// 拷贝pos最右边为1的bit,其余bit置0,也就是取得可以放皇后的最右边的列。
long p = pos & -pos; /*将pos最右边为1的bit清零,也就是为获取下一次
的最右可用列使用做准备,程序将来会回溯到这个位置继续试探。*/
pos -= p; /*row + p,将当前列置1,表示记录这次皇后放置的列。
(ld + p) << 1,标记当前皇后左边相邻的列不允许下一个皇后放置。
(ld + p) >> 1,标记当前皇后右边相邻的列不允许下一个皇后放置。
此处的移位操作实际上是记录对角线上的限制,只是因为问题都化归
到一行网格上来解决,所以表示为列的限制就可以了。显然,随着移位
在每次选择列之前进行,原来N×N网格中某个已放置的皇后针对其对角线
上产生的限制都被记录下来了。 */
test(row + p, (ld + p) << 1, (rd + p) >> 1);
}
}
else
{
// row的所有位都为1,即找到了一个成功的布局,回溯。
sum++;
}
}
int main()
{
time_t tm;
int n;
while(scanf("%d",&n)&&n!=0)
{
upperlim=1;
sum=0;
upperlim = (upperlim << n) - 1; /*即upperlim=2^n-1(2的n次方减1),
使得低n位都为1,其余位都为0*/
test(0, 0, 0);
printf("%ld/n",sum);
}
system("pause");
return 0;
}
相关文章推荐
- HDU N皇后——高效方法详解(bit方法)
- 海量数据处理方法--十七道海量数据处理面试题与Bit-map详解(转)
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
- 如何高效使用Python字典的方法详解
- 线段树求矩形面积并 方法详解 (扫描线)HDU 1542 & HDU 3265 & POJ 1151
- 深入N皇后问题的两个最高效算法的详解[装载]
- cocoapods版本上传新方法步骤详解-无需checkout原始库,高效!
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
- BestCoder Round #89 1002 && HDU 5945 详解(单调队列+DP)加一种错误的方法
- 深入N皇后问题的两个最高效算法的详解 分类: C/C++ 2014-11-08 17:22 117人阅读 评论(0) 收藏
- 深入N皇后问题的一个高效算法的详解
- 深入N皇后问题的两个最高效算法的详解
- 深入N皇后问题的两个最高效算法的详解
- hdu 1874 dijkstra 队列实现 比数组高效特别在稀疏图
- Linux操作系统下IPTables配置方法详解
- JavaScript中的substr()方法使用详解
- js中Math对象属性和方法详解