问题描述:
根据中国象棋的规则,将和帅被限制在己方田字格中运动,并且不能碰面,求出将帅的所有合法位置。
要求:代码中只用一个变量。
问题分析:
给将和帅的位置信息进行编号,如上图所示。然后,
遍历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; }运行结果: