zoukankan      html  css  js  c++  java
  • 位运算枚举解决象棋将帅问题

    引子问题:
    在一把象棋的残局中,象棋双方的将帅不可以相见,即不可以在中间没有其他棋子的情况下在同一列出现。
    而将、帅各被限制在己方的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<stdio.h>
     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<stdio.h>
    17 int main(void)
    18 {
    19     struct
    20     {
    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<stdio.h>
    35 int main(void)
    36 {
    37     struct test
    38     {
    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<stdio.h>
    50 int main(void)
    51 {
    52     struct test
    53     {
    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<stdio.h>
    61 int main(void)
    62 {
    63     struct test
    64     {
    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<stdio.h>
    74 struct m
    75 {
    76     char a;
    77     int b;
    78     char c;
    79 }x;
    80 struct n
    81 {
    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://15838341661-139-com.iteye.com/blog/1601987

    
    
  • 相关阅读:
    [SSRS] Use Enum values in filter expressions Dynamics 365 Finance and Operation
    Power shell deploy all SSRS report d365 FO
    display method in Dynamics 365 FO
    How To Debug Dynamics 365 Finance and Operation
    Computed columns and virtual fields in data entities Dynamics 365
    Azure DevOps for Power Platform Build Pipeline
    Create readonly entities that expose financial dimensions Dynamics 365
    Dataentity call stack dynamics 365
    Dynamics 365 FO extension
    Use singletenant servertoserver authentication PowerApps
  • 原文地址:https://www.cnblogs.com/hxsyl/p/2693531.html
Copyright © 2011-2022 走看看