找到可以达到多少点?

时间:2014-04-02 14:04:19

标签: algorithm data-structures geometry computational-geometry

输入:

  • 一组点(整数坐标)(2D空间)
  • 一组确定限制的整数

输出:

  • 对于集合中的每个limit,输出可以从第一个点到达的点数。
  • A可以达到B iff AB <= limit

我目前的解决方案:

  • 计算每个点之间的所有距离
  • 对它们进行排序
  • 对于每个限制,使用DFS计算有多少点

问题:

对于一大组限制,程序将运行缓慢(我需要为每个查询重新进行DFS)。我可以使用什么算法/数据结构来获得更好的性能?

3 个答案:

答案 0 :(得分:1)

将所有对存储在数组中,按距离排序 而不是DFS,在数组的左(较小)部分执行union-find algorithm。您将获得不相交(有时是联合)森林,其中包含第一个点的组件的等级是您想要的。

请注意,随着距离的增加,等级会单调增加。

现在从左到右遍历所有数组,并记下到Dist数组的距离,并达到Rank数组的第一个组件的等级。

现在为每个限制查询在Dist数组中找到此值位置索引(使用二进制搜索)并从Rank数组中获取相应的值 - 每个查询的复杂度为
为O(log(N ^ 2))= <强> O(的log(n))

答案 1 :(得分:0)

当考虑欧几里德距离时,具有整数坐标没有多大帮助:点(0,0)和(1,1)相隔sqrt(2),这不是整数,甚至不是理性的。幸运的是,您不必在距离上做任何算术,只需比较它们,这样您就可以存储和比较距离的整数平方。

我能看到的最佳方式(但我不是这类问题的专家!)是建立一个最小生成树(参见this comment),然后将其分成几部分:对于每个给定的限制删除超过该限制的分支,然后识别剩余的连接组件(Wikipedia) - 这些是您的“可达子集”。

如果从最大限制开始并进入最小限制,则可以迭代地执行任务:每个分支删除都会将分支所属的组件拆分为两部分,但不会影响其他组件。这可以简化工作,前提是数据结构允许有效地关联分支和子图。

答案 2 :(得分:0)

如果您使用Dijkstra算法进行最短路径查找的变体,请参阅https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm,您可以使用O(n*log(n))。这将标记所有点与一个起始点的距离。然后你只需排序(O(n*log(n)))并输出它们(O(n*l)以获得天真的方法;如果你有很多限制,那么先排序它们,最后得到O(n*log(n) + l*log(l)))。