我有 P 个点,它们的整数坐标(用(xi,yi)表示)。
0 <= xi <= n; 0 <= yi <= m (i = 1,2 ... P)
2 <= n,m <= 100
我很想找出相距 d 的点对数。显然,1 <= d <= m + n-2和P <= m * n。我想计算每个 d 的对数。最快的方法是什么? (我可以通过遍历d并为每个d检查每一对来找到它。这是非常缓慢的过程)
e.g.
points : (0,2);(0,3);(2,1)
for d=1 : 1 pair
for d=2 : 0 pairs
for d=3 : 1 pair
for d=4 : 1 pair
for d=5 : 0 pairs
答案 0 :(得分:1)
为什么不循环遍历所有点对并计算距离,并创建一个以键为距离和值为频率的地图?
for point P1 in P
for point P2 in P, P2 > P1
d <- distance(P1,P2)
if (mapDistance.get(d) exists)
increment mapDistance.get(d)
else
mapDistance.put(d,1)
总体复杂度为O(P * P)
答案 1 :(得分:0)
以下是具有N×M复杂度的算法,用于获取单个距离d的点对数。要获得所有距离的总和,请对d的每个值运行此算法。这样,总体复杂度将为N×M×(N + M),应符合时间约束。
(有一些替代方法;您可以构建一个网格,每个对角线的总和为1,然后减去两个数,以距离某一点的距离d读出每个对角线的1的个数。相似的理论复杂度,但实际上可能更快。)
(我们将使用给定的输入作为二进制网格,就像在CodeChef上的原始问题一样,而不是您建议的坐标列表。)
让我们看一下曼哈顿距离的几何:
6 5 4 3 4 5 6
5 4 3 2 3 4 5
4 3 2 1 2 3 4
3 2 1 X 1 2 3
4 3 2 1 2 3 4
5 4 3 2 3 4 5
6 5 4 3 4 5 6
您会注意到,距离d处的点在对角线上,在该点周围形成菱形,其中有4 d个。例如对于距离d = 3:
3
3 . 3
3 . . . 3
3 . . X . . 3
3 . . . 3
3 . 3
3
我们不想对每一对都计算两次,因此我们只看一下钻石四个侧面中的两个:
A
. . A
. . . . A
. . . X . . B
. . . . B
. . B
.
如果中心点X的值为1,则可以将点A和B的值的总和添加到距离d的对的总数中。
我们可以遍历网格以找到两个对角线运动的总和;首先,让我们检查每个点周围菱形右上角的点A。我们看一下彼此相距d的对角线,例如对于距离为3的7×6网格:
. . . . . . . . . . . . . . A . . . . . . . A . . . . .
. . . . . . . A . . . . . . . A . . . . . . . A . . . .
A . . . . . . . A . . . . . . . A . . . . X . . A . . .
. A . . . . . . . A . . . . X . . A . . . . X . . A . .
. . A . . . . X . . A . . . . X . . A . . . . X . . A .
X . . A . . . . X . . A . . . . X . . A . . . . X . . A etc...
对于每一个,我们迭代X对角线,如果点X的值为1,则将其上方的d点A的值之和加到总数中,例如:< / p>
A . . . . . . . . . . . . . . . . . . . .
. A . . . . . . A . . . . . . . . . . . .
. . A . . . . . . A . . . . . . A . . . .
X . . . . . . . . . A . . . . . . A . . .
. . . . . . . . X . . . . . . . . . A . .
. . . . . . . . . . . . . . . . X . . . .
如您所见,可以使用滑动窗口来计算d点A的值之和,因此我们只需要对每个对角线上的值进行一次迭代。
然后我们对另一个方向的对角线进行相同操作:
X . . B . . . . X . . B . . . . X . . B . . . . X . . B
. . B . . . . X . . B . . . . X . . B . . . . X . . B .
. B . . . . . . . B . . . . X . . B . . . . X . . B . .
B . . . . . . . B . . . . . . . B . . . . X . . B . . .
. . . . . . . B . . . . . . . B . . . . . . . B . . . .
. . . . . . . . . . . . . . B . . . . . . . B . . . . . etc...
我们对每个对角线(在两个方向上)进行一次迭代,因此最终我们对每个点进行了两次迭代,并且算法的复杂度与M×N成线性关系。