现在的位置: 首页 > 综合 > 正文

编程之美 1.2 中国象棋将帅问题

2018年01月19日 ⁄ 综合 ⁄ 共 1262字 ⁄ 字号 评论关闭

中国象棋将帅问题

问题描述:
在中国象棋规则中,将和帅规定只能在田字格中移动,且将和帅是不能碰面的,

请求解出所有可能的符合规则的将帅位置。

A:

B:

限制条件:
只能使用一个字节的变量

问题解答:
解法很简单,不在一条直线,%3不相等即可;
如何只用一个字节来表示所有需要用到变量,是关键。 

解法一:用位表示变量  

8位可以表示2^8=256个值,前4bit表示A,后4bit表示B;

#include<iostream>
#include<stdio.h> 
using namespace std;

#define HALF_BITS_LENGTH  4  //存储单元长度的一半,即4位
#define FULLMASK 255 //存储单元全部bit的mask(掩码),11111111,为0Xff; 
#define LMASK (FULLMASK<<HALF_BITS_LENGTH)   //左四位,11110000,0xf0 
#define RMASK (FULLMASK>>HALF_BITS_LENGTH)   //右四位。00001111,0x0f

#define RSET(b,n) (b=((LMASK&b)|(n)))  
//将b的4位设置为n,首先清空右4位LMASK&b,然后|n;

#define LSET(b,n) (b = ((RMASK &b) | (n) << HALF_BITS_LENGTH)) 
//将b左4位设置为n,首先清空左4位RMASK&b,然后n左移4位,在进行|运算;

#define RGET(b) (RMASK&b) //得到b右四位的值
#define LGET(b) ((LMASK&b)>> HALF_BITS_LENGTH) //得到b左四位的值
#define GRIDW  3  // 九宫格边界长度
 
int main()
{
    unsigned char b;
    for(LSET(b,1);LGET(b)<=GRIDW*GRIDW ; LSET(b,(LGET(b)+1)))//左4位为A 
    {
        for(RSET(b,1);RGET(b)<=GRIDW*GRIDW;RSET(b,(RGET(b)+1)))//右4位为B
        {
            if(LGET(b)%GRIDW!=RGET(b)%GRIDW)
            {
                printf("A=%d,B=%d\n",LGET(b),RGET(b));
            }
        }
    }
    return 0;
}

解法二、 

整数i可以由部两分组成,即i=(i/9)*9+i%9 ,其中i<n。
我们注意到,在i从81到0变化的过程中,i%9的变化相当于内层循环(0,1,2..8),
i/9的变话相对于外层循环(0,1...8),一个表示对面的,一个表示自己的 

#include<iostream>
using namespace std;
typedef unsigned char BYTE;
int main()
{
	BYTE i=81;//9*9
	while(i--)
	{
		if(i/9%3==i%9%3)//内层循环%3,外层循环%3,相等在一条直线 
			continue;
		cout<<"A= "<<i/9+1<<",B= "<<i%9+1<<endl;
	}
	return 0;
}

抱歉!评论已关闭.