好的,如承诺的一样,这里是一个简单的解决方案:
符号说明:设 d_{i,j}=d_{j,i}
表示点 i
和 j
之间的平方距离。设 N
表示点的数量。设 p_i
表示点 i
,p_{i,k}
表示点的第 k
个坐标。
希望我现在能正确地推导出算法。稍后会有一些解释,以便您可以检查推导过程(我讨厌出现许多指数时的感觉)。
该算法使用动态规划来得出正确的解决方案。
Initialization:
p_{i,k} := 0 for all i and k
Calculation:
for i = 2 to N do
sum = 0
for j = 2 to i - 1 do
accu = d_{i,j} - d_{i,1} - p_{j,j-1}^2
for k = 1 to j-1 do
accu = accu + 2 p_{i,k}*p_{j,k} - p_{j,k}^2
done
p_{i,j} = accu / ( 2 p_{j,j-1} )
sum = sum + p_{i,j}^2
done
p_{i,i-1} = sqrt( d_{i,0} - sum )
done
如果我没有犯任何严重的索引错误(我通常会犯),这应该能解决问题。
这背后的想法:
我们将第一个点任意设置为原点,以使我们的生活更轻松。对于点 p_i
,我们从不在 k > i-1
时设置坐标 k
。也就是说,对于第二个点,我们只设置第一个坐标,对于第三个点,我们只设置第一个和第二个坐标等等。
现在假设我们已经有了所有点 p_{k'} 的坐标,其中 k'<i
,我们想要计算 p_{i}
的坐标,以满足所有的 d_{i,k'}
(我们还不关心 k>k'
的点的任何约束)。如果我们写下方程组,我们有:
d_{i,j} = \sum_{k=1}^N (p_{i,k} - p_{j,k} )^2
因为对于 k>k'
,p_{i,k}
和 p_{j,k}
都等于零,所以我们可以将其简化为:
d_{i,j} = \sum_{k=1}^k' (p_{i,k} - p_{j,k})^2
请注意,根据循环不变式,当k>j-1
时,所有的p_{j,k}
都将为零。因此,我们将这个方程分成两部分:
d_{i,j} = \sum_{k=1}^{j-1} (p_{i,k} - p_{j,k})^2 + \sum_{k=j}^{k'} p_{i,j}^2
对于第一个方程,我们得到:
d_{i,1} = \sum_{k=1}^{j-1} (p_{i,k} - p_{j,k})^2 + \sum_{k=j}^{k'} p_i{i,1}^2
这个需要稍后进行特殊处理。
现在,如果我们解决正常方程中的所有二项式,我们得到:
d_{i,j} = \sum_{k=1}^{j-1} p_{i,k}^2 - 2 p_{i,k} p_{j,k} + p_{j,k}^2 + \sum_{k=j}^{k'} p_{i,j}^2
将第一个方程式从中减去,你会得到:
d_{i,j} - d_{i,1} = \sum_{k=1}^{j-1} p_{j,k}^2 - 2 p_{i,k} p_{j,k}
对于所有的 j > 1。
如果你看一下这个式子,你会发现所有的 p_i 坐标的平方都消失了,我们只需要已知的平方。这是一组线性方程,可以使用线性代数的方法轻松解决。实际上,这组方程还有一个特殊之处:这些方程已经处于三角形式,所以你只需要进行最后一步解决方案的传递。对于最后一步,我们只剩下一个二次方程,我们可以通过取一个平方根来解决它。
希望你能理解我的推理。现在有点晚了,我的头有点晕乎乎的。
编辑:是的,有一些索引错误。已经修复。我会在有时间的时候尝试用Python实现它以进行测试。