最近买到了《编程之美》这本书,此题是里面的一道题目
题目
下过象棋的朋友都知道,双方的“将”和“帅”相隔遥远,且不能照面, 并且只能在各自的田字格中左右和上下移动,且只能移动一步。用A表示“将”,用B表示“帅”,那么AB不能面对面,即不能出现在同一条直线上。现在请写出一个程序,输出A、B所有的有效位置。要求在代码中只能使用一个变量(注意:只能使用一个变量)。
代码实现
下面是书中给出的一种代码实现:
看完这段代码,朋友们是否明白了其原理呢?如果没有明白,那么请看下面Mr Guo的一些分析来帮助你理解;如果已经明白,也请看下面的分析,若有更好的想法,或发现了错误及不足,请不吝赐教!
分析
首先,我们得明白基本的算法!
--------------
| 1 | 2 | 3 |
--------------
| 4 | 5 | 6 |
--------------
| 7 | 8 | 9 |
--------------
现在以上图表示想起的九宫格,根据规则,A、B不能同时处于一条直线上;经观察在A、B处于一条直线上时,A%3 = B%3(例如(1,4)、(2,5)、(3,6)···)。所有可能的位置种数为9*9=81种。现在看程序中是如何用i来表示9*9的。
i∈[73,81]时,i%9∈[0,8],i/9=8(注意while中为i--,因此在循环中i要减一)
i∈[63,72]时,i%9∈[0,8],i/9=7
······
如此看来i/9分别为0、1、2、···、8时,i%9都有0-8 9种取值,如此是否就实现了9*9呢?!
再根据A%3 = B%3时不符合规则,在其他情况下则分别输出,这样就很简洁地实现了用一个变量计算所有可能方案的方法了。
其实这个程序基本的算法并不难,主要是在于其能运用做除运算与做余运算来实现用数字替代81种方案;一般很容易想到的是用两个变量来表示,还有人回使用一个变量的比特位来分别表示这两个9,但是个人觉得无论是哪种方法,都不如上面的方法更体现出算法的味道,他才正真地灵活运用了所学的数学知识!
微软研究院的的确是牛啊,不服不行啊···
以上观点仅为个人观点,如果有哪位技术大牛感到不屑,请手下留情啊···