这是我接受采访时总结的问题陈述:
有一个
n x n
网格代表一个城市,以及k
的列表 三元组(x, y, w)
,其中(x, y)
是事件的坐标,w
是事件的“价值”。您还获得了半径r
,代表您可以看到的距离。您从看到事件中得到幸福h
,从h=w/d
中得到幸福,其中d
为(1 +到事件的欧几里得距离)(以0表示距离)。如果d
大于r
,则幸福度为0。输出坐标(x,y)
,其累积幸福度最高。
除了蛮力逼迫每个可能的坐标并计算每个点的幸福感,记录最大值外,我真的不知道该如何解决这个问题。我还考虑过计算点的质心并找到与质心最接近的整数坐标,但这并没有适当考虑事件的“价值”。
解决此问题的最佳方法是什么?
答案 0 :(得分:2)
(为此,我看不到明显的最佳算法或数据结构;这可能是他们想要比您的解决方案更能听到您的思考过程的那些问题之一。)
两种明显的方法中的一种:
后者似乎是最有效的。您永远不会在寻找毫无价值的位置,并且要分配价值,只需计算圆的一个八分圆,然后将其镜像到圆的其余部分。
您显然需要存储空间来存储位置值的矩形网格,因此需要考虑。而且,如果您事先不知道城市的大小,则只需要选择一次网格大小就可以对输入进行迭代。 (相反,第一种方法几乎不需要存储空间)。
在时间复杂度方面,您需要遍历 k 个事件,并且对于每个事件,您都必须计算与 r 相关的多个位置的价值2 。在迭代事件时可以保持最大值,因此找到最大值不会增加时间复杂度。 (在第一种方法中,显然必须计算所有相同的 w /(d + 1)值,而没有镜像圆的一个八分圆以及至少所有圆的距离的优势。其他无用的位置。)
如果事件的数量和周围的影响区域与城市规模相比较小,则第二种方法的优势显而易见。如果存在大量事件和/或 r 很大,则差异可能并不明显。
可能有一些数学技巧来决定首先检查哪些事件,忽略哪些事件或何时停止,但是您必须了解一些更多的细节,例如两个事件是否可以在同一位置发生。可能有在按价值对事件进行排序并首先查看最有价值的事件方面具有优势,因为在某些时候,可以忽略当前最大值附近“热点”之外的事件,这很明显。但是,这很大程度上取决于数据的细节。
更新
将事件的价值分配到事件周围的位置时,您显然不必多次计算距离;例如如果 r = 3 ,您将使用权重为 1 / d 的7×7网格:
0 0 0 0.250 0 0 0
0 0.261 0.309 0.333 0.309 0.261 0
0 0.309 0.414 0.500 0.414 0.309 0
0.250 0.333 0.500 1.000 0.500 0.333 0.250
0 0.309 0.414 0.500 0.414 0.309 0
0 0.261 0.309 0.333 0.309 0.261 0
0 0 0 0.250 0 0 0
其中仅包含八个不同的值。然后,您可以使用它作为模板在事件的位置叠加在网格顶部,并将事件的价值与权重相乘,然后将它们添加到每个位置的价值中。
更新
我考虑了只有发生事件的地点才是价值最高的地点而没有限制 r 的可能性。那将使问题大为不同。但是,创建反例很容易。考虑例如这些事件:
- - 60 - -
- - - - -
60 - - - 60
- - - - -
- - 60 - -
限制 r 大于4,他们将在其周围的位置中创建此价值:
61.92 73.28 103.3 73.28 61.92
73.28 78.54 82.08 78.54 73.28
103.3 82.08 80.00 82.08 103.3
73.28 78.54 82.08 78.54 73.28
61.92 73.28 103.3 73.28 61.92
具有最高价值103.3的位置是事件的位置。但是,如果我们设置限制 r = 2 ,则会得到:
40 30 60 30 40
30 49.7 30 49.7 30
60 30 80 30 60
30 49.7 30 49.7 30
40 30 60 30 40
中间没有事件的位置现在是最大值80的位置。
这意味着必须考虑没有事件的位置,至少是围绕事件簇的凸包中的那些位置。当然,如果发现两个事件簇彼此之间的距离大于 2×r ,则可以将它们视为单独的区域。在这种情况下,您将不必为整个城市创建网格,而只需在每个群集周围分离较小的网格。
所以总体方法是: