一道挺好玩的算法题,不知道各位有没有更好的想法

2017-05-16 10:01:44 +08:00
 XiongZaizi

小弟这几天在做算法题目,看到一个很 interesting 的题目,贴图如下:

简单描述下题目内容:这根木棍向右倒,在经过点 a 坐标之后,下一次在重合到一点时,输出离原点最近的那一点的坐标。 举个栗子:如下图

上图重合点是 5,3 这个点,接下来重合的点是 2,1 4,2 6,3 那么离原点最近的点就是 2,1。

我的想法就是: 1、穷举出木棍 l 能扫过的所有的点,然后计算每个点到原点的距离,以及和横轴的夹角。按照角度进行快速排序;

2、计算与点 a 重合时,木棍和横轴的夹角,抽取出小于该夹角的所有点

3、对抽取出来的点按照距离进行一次遍历,找到距离原点最小的点进行输出

总感觉这个算法有点复杂,不知道有没有更巧妙地算法?还请大家开动脑洞讨论讨论

4349 次点击
所在节点    算法
35 条回复
grimpil
2017-05-16 10:40:27 +08:00
题目看不明白。点 a 是哪个点?重合到一点是什么意思?
blankme
2017-05-16 10:48:21 +08:00
建议贴原题,不要“简单描述题目内容”,你根本没描述清楚题目。
yangff
2017-05-16 10:54:13 +08:00
没理解错的话,没跨过(1,1)之前最近的是(1,1),跨过(x,1)之后最近的是(x+1,1);因为只需要考虑 gcd(x,y)==1 的点,所以扫过符合要求的 x 的时候,每个 x 显然能符合要求的最小的 y 是 1
XiongZaizi
2017-05-16 11:01:35 +08:00
@blankme 原题是日语的,我只能简单的进行翻译了。。。哪里不明白可以说一下
jmc891205
2017-05-16 11:04:37 +08:00
那些斜率一样的点只要记一个到原点距离最小的就可以了
这样你的第一步快排之后就有了一个按斜率(角度)递增的数组
之后只要拿 A 点的斜率做一次二分查找 找到的那个点的前一个点就是结果
XiongZaizi
2017-05-16 11:04:49 +08:00
@grimpil a 是随机输入的一个点,是棍子能够扫到的任何一点;重合到一点就是就是棍子在向下扫的时候,接触到的点。可以看第二个图,图中画的那条线就假设是棍子,在向下倒的时候,接触到了 5,3 这个点,这种情况就叫做重合
Vinty
2017-05-16 11:05:59 +08:00
大概就是求一个比 a/b 小的最大的两个整数之比 x/y,x/y 有公约数,化简一下即可
whalegia
2017-05-16 11:08:27 +08:00
重合是什么意思?
为什么 ( 5,3 )后是( 2,1 ),( 2,1 )后是( 4,2 )?
感觉我哪里都不明白,对不去语文老师
XiongZaizi
2017-05-16 11:08:34 +08:00
@jmc891205 有道理呢,这样能减少很大一部分的操作量了。多谢了
XiongZaizi
2017-05-16 11:14:10 +08:00
@whalegia 第二张图中实线是假设的棍子,这根棍子没有题目中的那么长,此时棍子接触到了点 5,3,棍子继续向下倒的时候,最先接触点 2,1,再接触点 4,2。
Vinty
2017-05-16 11:14:57 +08:00
接 7l,这个值应该等于(ma-1)/(mb-1),m 是令该点在可行域内的最大整数
XiongZaizi
2017-05-16 11:15:44 +08:00
@yangff 那这样看来只有 y=1 的点是符合要求的,说的有道理
XiongZaizi
2017-05-16 11:25:41 +08:00
@Vinty “大概就是求一个比 a/b 小的最大的两个整数之比 x/y,x/y 有公约数,化简一下即可”,这一步是求出下一个杰出的点的吧?还有后面那个公式是咋计算的?
liuminghao233
2017-05-16 14:00:41 +08:00
根本就不知道你在说什么 什么 a 点
Vinty
2017-05-16 14:37:41 +08:00
@XiongZaizi 11l 的公式是我猜的,好像不对。。一是只考虑了小于 45°的情况,二是对可行域处理的不好。如果点的数量比较少的话,就列出可行域内的所有点按正切值做个排序就行了。如果是点非常复杂的话,那就找到目前过( a,b )这条线和边界的交点( u,v ),向下取整得到( u',v')。比较( u',v'),( u'+1,v'),( u',v'-1 ),( u'+1,v'-1 )四点即可,也许还有( u'-1,v'-1 )。
反正就是比较周围几个点看在不在可行域内哪个最大,具体哪几个也许可以简化一下。
imn1
2017-05-16 15:16:55 +08:00
下一次在重合到一点时,输出离原点最近的那一点的坐标
-------------------------------------------------------------------------
这句话是要再解释清楚的

“下一次在重合到一点时”,换言之,重合 A 到这次重合中间没有再重合任何点了,下半句“那一点”指的是什么?
lingo
2017-05-16 18:04:39 +08:00
哈哈哈哈哈题目看不懂
XiongZaizi
2017-05-16 18:10:40 +08:00
@Vinty 恩恩,谢谢了,这样也是一种方法
XiongZaizi
2017-05-16 18:16:41 +08:00
@imn1 就是棍子在向下倒的这个过程中,会接触到点格中的点,那么假设其中有一时刻棍子和给定的能够接触到的点 a 接触了记为时刻 t1,从这一时刻起开始,棍子继续向下倒,又会接触一个新的点 b,时刻记为 t2。这 t1 和 t2 两个时刻之间,棍子没有和任何的点接触。所要求的就是从 t1 时刻开始,到棍子最终倒在横轴上这一段时间里,棍子所能接触到的所有点中,距离原点最小的一点。
ZyZyZzz
2017-05-16 18:24:47 +08:00
你直接把日语题干贴出来吧,这里有的是人懂日语
不懂的还可以去机翻

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/361597

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX