博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
位运算枚举解决象棋将帅问题
阅读量:6676 次
发布时间:2019-06-25

本文共 3350 字,大约阅读时间需要 11 分钟。

引子问题: 在一把象棋的残局中,象棋双方的将帅不可以相见,即不可以在中间没有其他棋子的情况下在同一列出现。 而将、帅各被限制在己方的3*3的格子中运动。相信大家都非常熟悉象棋的玩法吧,这里就不详细说明游戏规则了。  用A、B代表将和帅,请写出一个程序,输出A、B所有合法的位置。要求在代码中只能用一个变量。
中国象棋将帅问题:
分析与解法:
这个问题的解法并不复杂。
遍历A的所有位置
遍历B的所有位置
如果A的位置和B的位置在同一列
输出结果
否则      继续寻找
地图可以用0-8表示A或B可能的9个位置
0------1------2
3------4------5
6------7------8
关键问题在于只使用一个变量来表示A和B的位置。所以可以使用位运算来解决。一个无符号字符类型的长度是1字节,也就是8位,8位可以表示2^8=256个值,对于A、B的9个位置来说足够。可以用前4位来表示A的位置情况,后4位表示B的位置情况。而4位可以表示16个数也足够表示A、B的位置情况了。
通过位运算可以对A、B的位置进行读取和修改。
几种基本的位运算:
(1)&  按位与运算
(2)| 按位或运算  "与"和"或"就不用说了吧
(3)^ 按位异或运算 相同为假,不同为真
(4)~ 按位取反 一元运算符
(5)<< 按位左移  如 0000 0111 << 2 = 0001 1100,将此数左移两位相当于将此数扩大两倍。
(6)>> 按位右移 如  0001 1000 >> 2 = 0000 0110,将此数右移两位相当于将此数缩小两倍。
令LMASK为1111 0000,另任意一个1字节的字符型变量与其做与运算,结果右移四位,便可得到此变量的高四位的值。
Example,
0110 1011
&1111 0000
= 0110 0000 >> 4 = 0000 0110
同理,令RMASK为0000 1111,即可得到它低四位的值。
Ex.
0110 1011
& 0000 1111
= 0000 1011
设置1字节字符型变量,比如对高四位进行设置,先将变量与RMASK相与,将要修改的变量左移四位后于前一结果进行“异或”或“或运算”。
Ex.将0110 1011高四位设置为1001.
0110 1011
& 0000 1111
= 0000 1011              0000 1001 << 4 = 1001 0000
^ 1001 0000
= 1001 1011
同样的方法设置低四位的值。
1 #include
2 #define BYTE unsigned char 3 int main(void) 4 { 5 BYTE i = 81; 6 while(i--) 7 { 8 if((i / 9) % 3 == (i % 9) % 3) 9 continue;10 printf("A = %d, B = %d\n", i /9 + 1, i%9 + 1);11 }12 return 0;13 }14 可以把变量i想象成一个两位九进制的变量,而i在计算机中存储的值是i的十进制表示。则i/9的计算机处理结果,即结果直接去掉小数点后部分的结果即是此九进制数的第二位,而i%9即是此九进制数的个位。本程序用此九进制数的第二位保存A的位置,个位表示B的位置。最大值为88,即为十进制的80.程序从十进制的80,即九进制的88遍历到十进制的0,即九进制的0.将符合条件的位置全部输出。15 第二个:16 #include
17 int main(void)18 {19 struct20 {21 unsigned char a:4;22 unsigned char b:4;23 }i;24 for(i.a = 1; i.a <= 9; i.a++)25 for(i.b = 1; i.b <= 9; i.b++)26 if(i.a % 3 != i.b % 3)27 printf("A = %d, B = %d\n", i.a, i.b);28 return 0;29 }30 算法与上面的如出一辙。31 其中unsigned char a:4表示结构体中a的位域只有4位,高位用作它用。只能在结构体里使用,建议尽量少用,会破坏程序的移植性。32 当结构体中的元素的取值范围很小时,可以将几个字段按位合成一个字段来表示,起到节省内存空间的作用。33 Ex:34 #include
35 int main(void)36 {37 struct test38 {39 unsigned char a:4;40 unsigned char b:4;41 }i;42 i.a = 15;43 i.b = 10;44 printf("%d\n", sizeof(i));45 }46 将上面例子中的变量i的大小输出,结果为1字节。说明i.a和i.b各占4位。47 结构体是C语言中的一种常用的自定义数据结构。48 看下面的例子:49 #include
50 int main(void)51 {52 struct test53 {54 int a;55 char b;56 }i;57 printf("%d\n",sizeof(i));58 }59 按理说结构体变量i的大小应该是sizeof(int)+sizeof(char),即5,而输出显示的结果为8。再看一个例子:60 #include
61 int main(void)62 {63 struct test64 {65 int a;66 char b,c;67 }i;68 printf("%d\n",sizeof(i));69 }70 应该是6对吧?结果还是8.这是为什么呢?71 这是因为在32位的操作系统上,操作系统组织数据是以32位(4个字节)作为一个标准,因此各种变量的size都一般都是4的倍数。而且结构体数据都是按照定义时所使用的顺序存放的,因此在第一个例子中尽管b变量只会占有一个字节,但是a + b = 5 > 4,因此第一个4个字节存放a,第二个4个字节用于存放b,这样实际上就浪费了3个字节。在第二个例子中第二个4个字节用来存放b和c。72 所以,在结构体中要注意结构体中的变量定义的顺序,不同的顺序可能会造成占用空间的不同。这在嵌入式程序设计等系统资源比较少的情况下尤为重要。比如如下两种结构体:73 #include
74 struct m75 {76 char a;77 int b;78 char c;79 }x;80 struct n81 {82 char a;83 char c;84 int b;85 }y;86 int main(void)87 {88 printf("m:%d\nn:%d\n", sizeof(x), sizeof(y));89 return 0;90 }91 对于结构体m来说,x变量的大小为12,而y变量的大小为8.编译器是按程序员在结构体中声明变量的顺序处理的。不当的顺序会造成空间的浪费。读者可以想到发生这样情况的原因的。所以建议声明结构体时,按照不同变量的类型,按占用空间的大小升序或降序声明会取得较好的空间占用。

 不理解的话可继续参考:

 

转载地址:http://iprxo.baihongyu.com/

你可能感兴趣的文章
开源|基于TensorFlow的聊天机器人-ErGo
查看>>
lucene4.0入门1
查看>>
Svn结合hook实现自动更新及多Project管理更新
查看>>
第三十六讲:tapestry表单组件详解之PasswordField
查看>>
Ubuntu11.10下安装JDK+Eclipse+Maven
查看>>
sgu 222
查看>>
让spring-data-jpa解放你的DAO
查看>>
58沈剑:架构师的平凡之路
查看>>
Hibernate问题-read-write缓存策略
查看>>
C/C++语言中“:”的使用方法
查看>>
sql中实现汉字的拼音首字母查询
查看>>
Android 动态布局 (代码布局)
查看>>
MYSQL备份和恢复
查看>>
spark安装:在hadoop YARN上运行spark-shell
查看>>
Docker存储驱动之ZFS简介
查看>>
根据sql,一键生成excle 格式, 再通过 zip包压缩为zip
查看>>
PL/SQL Developer 添加数据
查看>>
PHP实时统计文件下载次数
查看>>
linux eth0 改eth1 在改ip
查看>>
乾颐堂鹏同学通过HCIE送给后来者的话
查看>>