题目大意
- 给定源点 和目标点
- 定义点的移动方式 和
- 数据范围:
问:源点经过任意次位移,是否有可能到达目标点?
分析
- 从数据范围来看,显然是不允许暴力搜索求解的。因此,这是一道巧妙的数学题(或者脑筋急转弯)。
- 两点都位于第一象限, 均为正整数,因此可以排除所有 和 的情况。
- 根据移动方式可知,将 中的较大值对对方取模,即可退回上个状态 。(这里思路不是很严谨)
求解
递归搜索的思路很简单,但会因为递归次数过多而栈溢出或因为搜索空间过大而超时。
bool reachingPoints(int sx, int sy, int tx, int ty) {
if (sx > tx || sy > ty)
return false;
if (sx == tx && sy == ty)
return true;
return reachingPoints(sx + sy, sy, tx, ty) || reachingPoints(sx, sx + sy, tx, ty);
}根据点的状态转移关系,我们可以将目标点尽量逼近源点,然后只需对剩下一个轴坐标做判断即可。
bool reachingPoints(int sx, int sy, int tx, int ty) {
if (sx > tx || sy > ty)
return false;
while (sx < tx && sy < ty) {
if (tx < ty)
ty %= tx;
else
tx %= ty;
}
// 每次循环只进行一次操作,因此循环结束时分两种情况
// 1. sx == tx:由于两点 x 不变,合法解只存在 ty = sy + n * sx
// 2. sy == ty:由于两点 y 不变,合法解只存在 tx = sx + n * sy
return (sx == tx && (ty - sy) % sx == 0) || (sy == ty && (tx - sx) % sy == 0);
}