二进制<3>
n皇后问题是啥我就不说了吧,学编程的肯定都见过。下面的十多行代码是n皇后问题的一个高效位运算程序,看到过的人都夸它牛。初始时,upperlim:=(1 shl n)-1。主程序调用test(0,0,0)后sum的值就是n皇后总的解数。拿这个去交USACO,0.3s,暴爽。
procedure test(row,ld,rd:longint);
var
pos,p:longint;
begin
{ 1} if row<>upperlim then
{ 2} begin
{ 3} pos:=upperlim and not (row or ld or rd);
{ 4} while pos<>0 do
{ 5} begin
{ 6} p:=pos and -pos;
{ 7} pos:=pos-p;
{ 8} test(row+p,(ld+p)shl 1,(rd+p)shr 1);
{ 9} end;
{10} end
{11} else inc(sum);
end;
乍一看似乎完全摸不着头脑,实际上整个程序是非常容易理解的。这里还是建议大家自己单步运行一探究竟,实在没研究出来再看下面的解说。
~~~~====~~~~===== 华丽的分割线 =====~~~~====~~~~
Gray码
假如我有4个潜在的GF,我需要决定最终到底和谁在一起。一个简单的办法就是,依次和每个MM交往一段时间,最后选择给我带来的“满意度”最大的MM。但看了dd牛的理论后,事情开始变得复杂了:我可以选择和多个MM在一起。这样,需要考核的状态变成了2^4=16种(当然包括0000这一状态,因为我有可能是玻璃)。现在的问题就是,我应该用什么顺序来遍历这16种状态呢?
传统的做法是,用二进制数的顺序来遍历所有可能的组合。也就是说,我需要以0000->0001->0010->0011->0100->...->1111这样的顺序对每种状态进行测试。这个顺序很不科学,很多时候状态的转移都很耗时。比如从0111到1000时我需要暂时甩掉当前所有的3个MM,然后去把第4个MM。同时改变所有MM与我的关系是一件何等巨大的工程啊。因此,我希望知道,是否有一种方法可以使得,从没有MM这一状态出发,每次只改变我和一个MM的关系(追或者甩),15次操作后恰好遍历完所有可能的组合(最终状态不一定是1111)。大家自己先试一试看行不行。
解决这个问题的方法很巧妙。我们来说明,假如我们已经知道了n=2时的合法遍历顺序,我们如何得到n=3的遍历顺序。显然,n=2的遍历顺序如下:
00
01
11
10
你可能已经想到了如何把上面的遍历顺序扩展到n=3的情况。n=3时一共有8种状态,其中前面4个把n=2的遍历顺序照搬下来,然后把它们对称翻折下去并在最前面加上1作为后面4个状态:
000
001
011
010 ↑
--------
110 ↓
111
101
100
用这种方法得到的遍历顺序显然符合要求。首先,上面8个状态恰好是n=3时的所有8种组合,因为它们是在n=2的全部四种组合的基础上考虑选不选第3个元素所得到的。然后我们看到,后面一半的状态应该和前面一半一样满足“相邻状态间仅一位不同”的限制,而“镜面”处则是最前面那一位数不同。再次翻折三阶遍历顺序,我们就得到了刚才的问题的答案:
0000
0001
0011
0010
0110
0111
0101
0100
1100
1101
1111
1110
1010
1011
1001
1000
这种遍历顺序作为一种编码方式存在,叫做Gray码(写个中文让蜘蛛来抓:格雷码)。它的应用范围很广。比如,n阶的Gray码相当于在n维立方体上的Hamilton回路,因为沿着立方体上的边走一步,n维坐标中只会有一个值改变。再比如,Gray码和Hanoi塔问题等价。Gray码改变的是第几个数,Hanoi塔就该移动哪个盘子。比如,3阶的Gray码每次改变的元素所在位置依次为1-2-1-3-1-2-1,这正好是3阶Hanoi塔每次移动盘子编号。如果我们可以快速求出Gray码的第n个数是多少,我们就可以输出任意步数后Hanoi塔的移动步骤。现在我告诉你,Gray码的第n个数(从0算起)是n xor (n shr 1),你能想出来这是为什么吗?先自己想想吧。
下面我们把二进制数和Gray码都写在下面,可以看到左边的数异或自身右移的结果就等于右边的数。
二进制数 Gray码
000 000
001 001
010 011
011 010
100 110
101 111
110 101
111 100
从二进制数的角度看,“镜像”位置上的数即是对原数进行not运算后的结果。比如,第3个数010和倒数第3个数101的每一位都正好相反。假设这两个数分别为x和y,那么x xor (x shr 1)和y xor (y shr 1)的结果只有一点不同:后者的首位是1,前者的首位是0。而这正好是Gray码的生成方法。这就说明了,Gray码的第n个数确实是n xor (n shr 1)。
今年四月份mashuo给我看了这道题,是二维意义上的Gray码。题目大意是说,把0到2^(n+m)-1的数写成2^n * 2^m的矩阵,使得位置相邻两数的二进制表示只有一位之差。答案其实很简单,所有数都是由m位的Gray码和n位Gray码拼接而成,需要用左移操作和or运算完成。完整的代码如下:var
x,y,m,n,u:longint;
begin
readln(m,n);
for x:=0 to 1 shl m-1 do begin
u:=(x xor (x shr 1)) shl n; //输出数的左边是一个m位的Gray码
for y:=0 to 1 shl n-1 do
write(u or (y xor (y shr 1)),' '); //并上一个n位Gray码
writeln;
end;
end.
二进制<3>的更多相关文章
- 使用struct处理二进制
有的时候需要用python处理二进制数据,比如,存取文件.socket操作时.这时候,可以使用python的struct模块来完成. struct模块中最重要的三个函数是pack(), unpack( ...
- 如何开启MySQL 5.7.12 的二进制日志
1. 打开/etc下的my.cnf文件 2. 编辑它,添加内容: log_bin=binary-log #二进制日志的文件名 server_id=1 #必须指定server_id,这是MySQL ...
- 【.net 深呼吸】使用二进制格式来压缩XML文档
在相当多的情况下,咱们写入XML文件默认是使用文本格式来写入的,如果XML内容是通过网络传输,或者希望节省空间,特别是对于XML文档较大的情况,是得考虑尽可能地压缩XML文件的大小. XmlDicti ...
- Javascript的二进制数据处理学习 ——nodejs环境和浏览器环境分别分析
以前用JavaScript主要是处理常规的数字.字符串.数组对象等数据,基本没有试过用JavaScript处理二进制数据块,最近的项目中涉及到这方面的东西,就花一段时间学了下这方面的API,在此总结一 ...
- 浅析MySQL基于ROW格式的二进制日志
上文分析的二进制日志实际上是基于STATEMENT格式的,下面我们来看看基于ROW格式的二进制日志,毕竟,两者对应的binlog事件类型也不一样,同时,很多童鞋反映基于ROW格式的二进制日志无法查到原 ...
- 浅析MySQL二进制日志
查看MySQL二进制文件中的内容有两种方式 1. mysqlbinlog 2. SHOW BINLOG EVENTS [IN 'log_name'] [FROM pos] [LIMIT [offs ...
- asp.net将图片转成二进制存入数据库
一.代码如下 int code = int.Parse(this.TextBox1.Text);//图片编码 string value = this.FileUpload1.PostedFile.Fi ...
- 二进制包安装MySQL数据库
1.1二进制包安装MySQL数据库 1.1.1 安装前准备(规范) [root@Mysql_server ~]# mkdir -p /home/zhurui/tools ##创建指定工具包存放路径 [ ...
- sqlite3的图片的(二进制数据)存取操作
sqlite3的图片的(二进制数据)存取操作 前言 上篇介绍了sqlite3的一些常用插入操作方法和注意事项,在实际项目中遇到了图片缓存的问题,由于服务器不是很稳定,且受到外界环境的干扰(例如断电 ...
- MySQL二进制日志
一.二进制日志(The Binary Log) 1.简介 包含所有更新了的数据或者已经潜在更新了的数据(比如一条没有匹配任何行的delete语句) 包含所有更新语句执行时间的信息 不记录没有修改数据的 ...
随机推荐
- python爬虫之路——变量和变量类型
变量类型: ①单值:int ②多值:数组 ③复杂:类 变量类型:就是变量的数据结构,表示这个变量所代表的内容的格式是怎样的. (多值)四种基本数据结构: 列表,字典,元组,集合 列表: ①元素可变, ...
- 在SAP C4C里触发SAP ERP的ATP check和Credit check
在C4C里创建一个新的Sales Quote: 添加三个行项目: 执行action "Request External Pricing"会从ERP更新pricing信息,触发ATP ...
- [dp][uestc oj][最长上升子序列] LIS N - 导弹拦截
N - 导弹拦截 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit ...
- HTML5中的webSocket、ajax、http
本文原链接:https://cloud.tencent.com/developer/article/1115496 https://cloud.tencent.com/developer/articl ...
- xpath定位和css定位对比
xpath定位和css定位对比 实际项目中使用较多的是xpath定位和css定位.XPath是XML文档中查找结点的语法,换句话就是通过元素的路径来查找这个元素.xpath比较强大,而css选择器 ...
- spring-data-JPA源码解读
spring-data-JPA源码部分有两个很重要的部分:1.识别repositories接口 2.将接口添加代理实现类并托管spring管理 JpaRepositoriesRegistrar 目的是 ...
- Oracle Real Application Clusters (RAC)
Oracle Real Application Clusters — 概述 包含 Oracle Real Application Clusters (RAC) 选件的 Oracle 数据库允许依托一组 ...
- Unity调用Windows窗口句柄,选择文件和目录
T:2019-6-25 10:06:59 C:Scatt Kang using System; using System.Collections; using System.Collections.G ...
- Cordova 本地项目创建方法
l 创建项目 需要在终端上输入:cordova create [目录][项目ID][APP名称] 运行:cordova create hello com.example.hello hello 将在 ...
- HDU-4848-Such Conquering
这题就是深搜加剪枝,有一个很明显的剪枝,因为题目中给出了一个deadline,所以我们一定要用这个deadline来进行剪枝. 题目的意思是求到达每个点的时间总和,当时把题看错了,卡了好久. 剪枝一: ...