【编程之美读书笔记】中国象棋将帅问题

问题描述:

根据中国象棋的规则,将和帅被限制在己方田字格中运动,并且不能碰面,求出将帅的所有合法位置。

要求:代码中只用一个变量。


问题分析:


给将和帅的位置信息进行编号,如上图所示。然后,

遍历A的位置

遍历B的位置

     判断A和B的位置是否满足要求

     如果满足,输出

问题解答:

编程之美中的第一种解法是将一个BYTE变量拆成两部分,前面4位代表将能走的位置,后面4位代表帅能走的位置,利用位操作来得到将和帅的合法位置。但第一种操作比较复杂,我也没有仔细看。第三种解法和第一种解法的思想相同,只不过用了位域的概念(位域具体可参见http://blog.csdn.net/ruan875417/article/details/43372093),但操作变得简单。因此,在这里我把它当做方法一。

方法一:

#include<iostream>
using namespace std;

struct{
    unsigned char a:4;
    unsigned char b:4;
}i;

int main(){
    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)
             printf("a=%d b=%d
",i.a,i.b);
    
    system("pause");
    return 0;
}

第二种解法是比较奇妙的,先给出完整的代码。

方法二:

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

int main(){
    BYTE i=81;
    while(i--){
       if(i/9%3==i%9%3)
          continue;
       printf("%d %d
",i/9+1,i%9+1);
    }
    system("pause");
    return 0;
}

将和帅各自有9个位置可以走,因此我们要验证9*9=81种位置关系。其次我们要知道i/9和i%9代表的意思。我们知道一个整数n=(n/9)*9+n%9,在i从81到0的变化过程中,n/9相当于外循环,n%9相当于内循环,这样我们就用一个变量同时表示了将和帅的位置。

扩展:如何用一个变量来表示三重循环,四重循环。。。n重循环。

对于a*b=i,

用如下公式展开:

loop1=i%b,

loop2=(i/b)%a

对于三重循环,可以看做a=m*n,

用公式展开:

loop1=i%b,

loop2=(i/b)%n,

loop3=((i/b)/n)%m

由此得到n重循环的公式:

设an* an-1*……* a2* a1=N,

loop1=i% a1

loop2=(i/ a1)% a2,

loop3=(i/( a1a2))%a3

……

loopn=(i/( a1a2…an))%an

最后,附上用一个变量实现三重循环的代码

#include<iostream>
#include <windows.h>
using namespace std;
int main(){
    BYTE i=5*4*3;
    while(i--){
       printf("n=%d i=%d j=%d k=%d 
",i,(i/(3*4))%5,(i/3)%4,i%3);
    }
    system("pause");
    return 0;
}
运行结果:




原文地址:https://www.cnblogs.com/ruan875417/p/4495582.html