今天看了《编程之美》-----中国象棋将帅问题,其中它解决问题的方法满特别的。
问题描述:
在中国的象棋规则中,将和帅只能在田字格中移动,且将和帅是不能碰面的(即使不能在纵向的同一
条直线上),请求解出所有符合可能的将帅位置。
限制条件:
只能使用一个字节的变量
问题分析:
因为只能在田字格内活动---在3*3中,可以将这些位置一一表示,则需要1-9即可。对于判断不能碰面
的方法是对于3的取余不能相同的位置组合,而对于只能使用一个字节变量的要求,则通过使用位操作来实现。
- 对位的操作:将一个变量所占用的二进制位数一分为二 。
- #include<stdio.h>
- #define HALF_BIT_LENGTH 4
- #define FULLMASK 255
- #define LMASK (FULLMASK<<HALF_BIT_LENGTH)
- #define RMASK (FULLMASK>>HALF_BIT_LENGTH)
- #define RSET(b,n) (b = ((LMASK&b)^n))
- #define LSET(b,n) (b = ((RMASK&b)^(n<<HALF_BIT_LENGTH)))
- #define RGET(b) (RMASK&b)
- #define LGET(b) ((LMASK&B)>>HALF_BIT_MASK)
- #define GRIDW 3
- int main()
- {
- unsigned char b ;
- for(LSET(b,1);LGET(b)<=GRIDW*GRIDW;LSET(b,(LGET(b)+1)))
- for(RSET(b,1);RGET(b)<=GRIDW*GRIDW;RSET(b,(RGET(b)+1)))
- if(LGET(b)%GRIDW != RGET(b)%GRIDW)
- printf("a = %d b = %d\n",LGET(b),RGET(b));
- }
- 等价的一重循环
- BYTE i= 81;
- while(i--)
- {
- if(i/9%3 == i%9%3)
- continue;
- printf("a = %d a = %d \n",i/9+1,i%9+1);
- }
- 位域等价操作
- struct {
- unsigned char a:4;
- unsigned char b:4;
- }i;
- for(i.a=1;i.a<=9;i.a++)
- for(i.b = 1;i.b<=9;i.b++)
- printf("a = %d b = %d \n",i.a,i.b);
批注:第一种和第三种的方法比较好理解,只有第二种方法却有点一头雾水的感觉,其实 可以先从 i/9 和 i%9 考虑 ,因为 i 使用 81到 1之间进行变化的,因此上面的两个表达式的值得范围都是 1-9。但是i/9中值变化的频率比i%9变化的频率要低,此时根据变化的情况i/9如同二重循环的第一重循环,而 i%9 相当于两重循环中的里面的循环
阅读(1672) | 评论(0) | 转发(1) |