来源:编程之美-微软技术面试心得
在中国象棋中,将帅只能在两个九宫格里,且将帅不能见面,即不能同时出现在一列里,
问题:请输出将帅所有可能的位置,只能用一个字节实现
分析:这个问题的难点在于变量只能使用一个字节,
很显然,大致的解法就是两个for循环,然后判断将帅是否在同一列,不在则输出。
设:A=‘将’,B=‘帅’,九宫格用1,2,3,……,9来表示。
解法一:
A或B可能的位置是九个,则可以使用4BIT来记录其位置,如此正好满足题目要求
编程中要使用到的操作就是位操作
1.设置低四位为n,保留高四位
先清除低四位:X&11110000
设置低四位:X|0000xxxx(n)
2.设置高四位,保留低四位
先清除高四位:X&00001111
设置高四位:X|xxxx1111(n)
3.分别输出高四位,低四位
输出高四位:X>>4
输出低四位:X&00001111
#include<stdio.h>
#define HALF_BITS_LENGHT 4
//记忆存储单元的一半
#define FULLMASK 255
//11111111
#define LMASK (FULL_MASK << HALF_BITS_LENGTH)
//11110000
$define RMASK (FULL_MASK >> HALF_BITS_LENGTH)
//00001111
#define RSET(b,n) (b = ((LMASK&b)|n))
//设置低四位为n,保留高四位
#define LSET(b,n) (b = ((RMASK&b)|(n<<HALF_BITS_LENGTH)))
//设置高四位,保留低四位
#define RGET(b) (RMASK&b)
//获取低四位
#define LGET(b) (LMASK&b)
//获取高四位
#define GRIDW 3
//定义棋盘
int main(){
unsigned char b;//定义变量
for(LSET(n,1);LGET(b)<=GRIDW*GRIDW;LSET(b,(LGET(b)+1))){
for(RSET(n,1);RGET(b)<=GRIDW*GRIDW;RSET(b,(RGET(b)+1))){
if(RGET(b)%GRIDW != LGET(b)%GRIDW){
printf("A=%d,B=%d\n",LGET(b),RGET(b));
}
}
}
return 0;
}
解法二:
很显然,A,B可能的组合是81种,(0,0)~(9,9)
BYTE i=81;
while(i--){
if(i / 9 % 3 == i % 9 % 3){
continue;
}
rintf("A=%d,B=%d\n",i/9+1,i%9+1);
}
解法三:
考虑到只能使用一个字节的存储空间
那么,可以使用位域的概念
位域的概念,参考http://blog.csdn.net/havedream_one/article/details/41541221
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++){
if(i.a %3!= i.b%3){
rintf("A=%d,B=%d\n",i.a,i.b);
}
}
}