There is a special square room with mirrors on each of the four walls. Except for the southwest corner, there are receptors on each of the remaining corners, numbered 0
, 1
, and 2
.
The square room has walls of length p
, and a laser ray from the southwest corner first meets the east wall at a distance q
from the 0
th receptor.
Return the number of the receptor that the ray meets first. (It is guaranteed that the ray will meet a receptor eventually.)
Example 1:
Input: p = 2, q = 1 Output: 2 Explanation: The ray meets receptor 2 the first time it gets reflected back to the left wall.
- 我的思路(略笨):
四面都是镜子的墙壁,光线从西南(左下)角出发,射向东边(右边)的镜子,经过多次反射最终会被一个接收器接收(0、1、2)。期间,南北(上下)墙壁镜子的作用只是改变光线的走向,设想一下,如果没有上下两面墙,而无线延伸左右两面墙,那么光线会被一直向上反射。因此,上下两面墙壁镜子会改变光线继续向上或向下反射,而向反方向前进,同时,光线从左边(右边)经过上/下镜子反射到达右边(左边)时,光线在左右两边镜子的触点与上/下镜子的距离之和等于q。
举个例子,假设光线从左边镜子上的A点经过下面镜子的反射到达右边镜子上的B点,A点到下方镜子的距离加上B点到下方镜子的距离之和为q,光线本来是向下反射的,但经过下方镜子的反射之后变为向上反射。现在有两个问题需要解决,如下:
第一,如何判断光线到达接收器? 利用上面的例子,p减去B点到下方镜子的距离再除以q,如果能除尽,则光线到达接收器,否则,光线会经过上方镜子的反射,改变方向,继续向下反射。
第二,如何判断光线到达哪个接收器? 光线最终达到的接收器只可能为0、1和2,到达接收器时可以分为两种情况,此时光线正往上反射或者正往下反射,如果光线是向上的,那么只会到达1或2,如果是向下的,只会到达0(题目说明光线一定会到达接收器,因此向下的光线一定会到达接收器0)。用flag参数代表光线的走向,一开始光线是向上的,flag = 0, 每一次走到上面的尽头,会反方向向下反射,flag++。d代表光线被反射到左右两面墙上的次数,即光线在左右两面镜子上的触点的总数,一开始光线从左下角出发,d为0,射向右边镜子,d加1,接着在反射到左边镜子,d再加一,可以看出,如果最终停止的时候,光线方向向上,且d为奇数,则到达接收器1,d为偶数到达接收器2,如果光线向下,则一定到达接收器0。
int mirrorReflection(int p, int q) {
int remain = 0;
int flag = 0;
int multi = 0;
int d = 0;
if(q == 0)
return 0;
if(q == p)
return 1;
remain = p % q;
multi = p/q;
d += multi;
while(remain != 0)
{
flag++;
d++;
remain = q - remain;
multi = (p - remain)/q;
d += multi;
remain = (p - remain)%q;
}
if(flag%2 == 0)
{
if(d%2 == 0)
return 2;
else
return 1;
}
else
{
return 0;
}
}
- 别人的思路(smart):
如上所述,如果没有上下两面镜子,光线会一直向上反射,这两面镜子的作用仅仅是改变了光线的走向而已。那么可以这样理解,假设没有上下两面镜子,无限延长左右两边的镜子长度,光线一直向上反射。同时,可以通过光线走过的纵向距离来判断光线是否到达接收点,如果此距离是p的奇数倍,那么光线到达上面的接收器,若此距离是p的偶数倍则光线到到下面的接收器,即接收器0。变量d记录光线与左右镜子接触的次数,同上,可根据d来判断光线到达接收器1和2。如果距离为p的奇数倍且d为奇数,则到达接收器1,若d为偶数则到达接收器2。
int mirrorReflection(int p, int q) {
int dist = 0;
int d = 0;
int remain;
while(1)
{
d++;
dist += q;
remain = dist%(2*p);
if(remain == p)
{
if(d%2 == 1)
return 1;
else
return 2;
}
if(remain == 0)
return 0;
}
}