- 问题提出
中国象棋的“将”,“帅”问题,他俩不能在一条直线上。求出他们的合法位置,并且只能用一个变量。
- 分析
一头雾水,不明所以。往下看了下,感觉像是程序员为难程序员的样子。只能用一个变量,并且只能用一个byte。一个byte有8位,前四位表示一个位置,后四位表示另一个位置。通过遍历位置找出互斥位置,并且去掉。大概思路是这样了。
- 书中的解法
第一种不是很懂,反正是操作一个byte的前四后四了。
第二种,超级巧妙。运用了81%9和81/9作为数集,遍历了(1-9)*(1-9)这个域。我在mac下找不到byte这个变量,实在要用的话是使用unsign char来代替,它也是表示1byte的变量。更巧妙的是,如果两个数除3的余数是相等的,那肯定是互斥位置。
int i = 81; while(i--){ if(i / 9 % 3 == i % 9 % 3) continue; cout<<"A = "<<(i/9 + 1)<<" B = "<<(i%9 + 1)<<endl; }
第三种,采用位域这个东西,把集合分成高位和低位存储,里面的变量更容易地去表示1-9,而且struct算一个变量?有点取巧。
struct { unsigned char a:4; unsigned char b:4; } i; cout<<sizeof(i)<<endl; for(i.a=1;i.a<=9;i.a++) for(i.b=1;i.b<=9;i.b++) if(i.a % 3 != i.b % 3) cout<<"A="<<(int)i.a<<" b="<<(int)i.b<<endl;
我自己的解法,并不能与各位大牛相提并论啊,只能用很多的常量去控制这个计算了。主要思想还是高位低位分开,高位控制外层循环,低位控制里层。每次里层循环跳出的时候就会清空低位。(这一堆位运算也是够晕的)想了很久,试了很久,也算有所得吧。
unsigned char c = 16; while((c&160) != 160){ c += 1; while((c&10) != 10){ if((c>>4)%3 != (c&15)%3) cout<<"A = "<<(c>>4)<<" B = "<<(c&15)<<endl; c ++; } c -= 10; c += 16; }