我正在学习测试,我无法解决这个问题:
我们得到一组 n< 1000 点和整数 d 。任务是创建两个不相交的点 A_1 和 A_2 (该联合被赋予 n 点的集合)以使得距离来自 A_i (对于i = 1或2)的每对点之间的(欧几里德)小于或等于 d 。如果无法打印,请打印 -1 。
例如,输入:
d = 3,并指出:
(5,3),(1,1),(4,2),(1,3),(5,2),(2,3),(5,1)
我们可以创建:
A_1 = {(2,3),(1,3),(1,1)}
A_2 = {(5,3),(4,2),(5,2),(5,1)}
因为来自A_i的每对点(对于i = 1或2)足够接近。
我真的想知道如何解决它,但不知道。由于n很小,算法甚至可以是O(n ^ 2 log n),但我不知道如何启动。我在想,也许从计算每对点之间的距离开始,然后取两个最大距离的点并将它们放入不同的组(如果它们的距离大于d)。然后对剩下的对重复此步骤,但问题是如何决定合法地放置下一个点的位置。任何人都可以帮助这个算法吗?
答案 0 :(得分:5)
让我们考虑一个带有 n 节点的简单图表(对应于 n 点)。如果两个对应点之间的距离大于 d ,则连接两个节点。
如果可以创建两个脱离集,我们必须有一个双向图(如果某些节点没有连接到其他节点,它们可以放在任何集中)。
因此,我们只需要测试图的二分性,这很简单:
http://en.wikipedia.org/wiki/Bipartite_graph#Testing_bipartiteness
答案 1 :(得分:1)
从距离矩阵开始似乎是一个好主意。然后在这个距离矩阵中挑选每个大于d的条目。此条目意味着相应的点必须在不同的集合中。
从两个空集开始并迭代所有相关条目(> d)。
如果集合为空,请将两个点放入其中。否则有三种选择:
我对第二种方法有了一个想法,它类似,但应该更快一点。
我们也从距离矩阵开始。
除了这两组之外,我们还维护一个堆栈,队列或任何新添加的条目。
因此,如果我们从距离矩阵中选择第一个相关条目,则将这些点添加到两个队列中。只要其中一个队列中有条目,请执行以下操作:
从队列中删除该点并将其插入到集合中。如果插入打破了最大距离标准,则问题无法解决。检查此点的距离矩阵中的行或列,并提取此行/列中的每个相关条目。将伙伴点添加到另一组的队列中(因为它必须位于不同的集合中)。
如果两个队列都为空,请将尚未访问过的下一个相关条目添加到队列中并重新开始。
该算法的优点是按照它们可以相互影响的顺序处理这些点。因此,不需要一对以上的套装。
答案 2 :(得分:1)
想想一个阵列,顶部的所有点和侧面的所有点。
如果定义单元格的两个点(左侧和顶部)大于d,则填充任何单元格中的零,如果两个点小于d,则填充一个。
(5,3), (1,1), (4,2), (1,3), (5,2), (2,3), (5,1)
(5,3), 0 1 0 1 1 1
(1,1), 0 0 1 0 1 0
(4,2), 1 0 0 1 1 1
(1,3), 0 1 0 0 1 0
(5,2), 1 0 1 0 0 1
(2,3), 1 1 1 1 0 0
(5,1) 1 0 1 0 1 0
(注意:您必须填写每个三角形,并翻转相同的0和1。)
忽略对角线。注意右上角的三角形部分。
跳过第0列。
从第1列开始,如果顶行没有1,则将其与右行的另一列交换,其中第一列的列为1。然后交换相同的行以保持对角线空白。 (如果没有,则没有解决方案。)[示例:交换第2列和第3列以及第2行和第3行]请注意,此行的选择可能会成为优化因素。
移动到下一列,如果它在顶行中没有1,则用右边的列交换并交换相应的行。如果没有,请尝试在其下方的行中交换该行,并在该列中包含1并执行相应的列。如果低于对角线,则应忽略它下面的行。
我们正在收集三角形左上角中有1个点的点。这些点都可以放在其中一个集合中。
这是我迷失在脑海中的地方,但你必须从三角形的右下角开始做一个类似的过程,并收集将在另一个集合中的点。交换行和相应的列以收集三角形右下角的1。
一旦你交换了足够的行,你可以在右上角形成一个矩形 - 一个没有左下角的真正矩形 - 这个矩形包含所有的0,你有一个解决方案。如果你不能这样做,那就没有办法解决。
最低行与三角形中的1和最右边的列进行比较,三角形中的1和它们相遇的单元格。该单元格必须位于三角形中才能找到解决方案。
(我给你留下了一个很大的“待办事项”,找到如何交错行和列的交换,以清除三角形的左上角和右下角的0。也许这里的讨论可以解决如何使它工作。或者发现它不起作用。)