找到位于大多数角度间隔中的角度
Finding the angle which is located in most intervals of angles
我有角度区间(以弧度为单位)[0,2π)
- 例如区间 [(2π)/3,(3π)/4]、[π/2,π] 等。
- 但也可能有间隔 [(3π)/2,π/3]
我必须找到位于大多数间隔的角度。 在C++找到它的最佳方式是什么? 如何表示角度间隔?
您可以实现一个简单的扫描线算法来解决此问题。
对于每个区间,将区间的开始和结束添加到向量中;对此向量进行排序,然后遍历它。如果您有任何跨越 2π 边界的区间,只需将其拆分为两个区间,它们都在 (0, 2π) 内。
当您遍历列表时,请跟踪当前点有多少重叠迭代,以及到目前为止您看到的最佳角度(以及在该角度重叠的间隔数)。到达终点后,您就知道最佳角度是什么。
如果您需要多个角度,您可以相当轻松地调整此方法以记住具有最大重叠的间隔,而不是单个角度。
我会通过将 [0, 2π] 的分区维护为对应于间隔覆盖率的范围来做到这一点,每个范围都有一个计数。首先,以下是算法在没有任何区间超过 0(或 2π)的条件下的工作方式。还假设间隔按如下方式归一化:如果间隔以 0 结束,则更改为以 2π 结束;如果从 2π 开始,则更改为从 0 开始。
- 创建(范围,计数)对的列表,使用单个范围 [0, 2π] 和计数 0 进行初始化。(列表将按范围的开头排序。列表中的范围只会在其端点处重叠,并且始终覆盖 [0, 2π])。
- 按如下所述处理每个间隔
- 扫描列表中具有最高计数的(范围,计数)对。任意解决关系。返回范围内的任意角度。
要处理间隔i
:
- 找到
i.start >= s.range.start
的第一个(范围,计数)对(称为s
)(即范围包含i.start
)。(请注意,如果i.start
是一个范围的结束,那么它将是另一个范围的开始;这将选择它是其开始的对。 - 查找
i.end <= e.range.end
的最后一个(范围、计数)对e
。(请注意,如果i.end
是一个范围的开始,那么它将是另一个范围的结束;这将选择它是结束的对。 - 如果
i.start > s.range.start
(i.range
从s
的内部开始),s
分成两对(范围,计数)s1 = ([s.range.start, i.start], s.count)
和s2 = ([i.start, s.range.end], s.count)
。将列表中的s
替换为s1
和s2
(按该顺序)。 - 如果
i.end < e.range.end
,则以与上一步平行的方式替换e
,使用i.end
进行拆分。 - 对于从
s
(如果s
在步骤 3 中拆分,则为s2
)到并包括e
(如果e
在步骤 4 中拆分,则e1
)的每一对,计数加 1。
如果您不关心跟踪包含特定角度的实际间隔数,只是因为它是最大值,那么跨 0(或 2π)的间隔的簿记更容易:只需取区间的补码(反转开始和结束)并从步骤 5 中的计数中减去一个而不是相加。如果您确实需要绝对计数,请执行补码技巧,然后将 1 添加到列表中的每个计数中。
以上不会正确处理相邻的区间(例如:[0, π/3] 和 [π/3, π];或 [2π/3, 2π] 和 [0, 1])。在这些情况下,据我了解,它们相邻的角度(π/3 或 0)应该算作两个间隔。可以调整上述算法,以便当间隔开始与范围终点重合时,在相关对之后插入一个新的(范围,计数)对;新对将具有单角度范围(即range.start == range.end
)。类似的过程将适用于从间隔结束时开始的范围。我认为通过这些调整,上述算法可以正确处理所有情况。
我的解决方案将涉及间隔开始的对列表以及有多少间隔重叠:
1 2 3 2 1
|---------|--------|-----|---------------|------|
|------------------|
|--------------|
|---------------------|
|----------------------------|
因此,对所有起点和终点进行排序,并遍历列表,为每个新间隔分配与其重叠的间隔计数(如果是起点,则增加它,否则减少)。然后从重叠计数中获取最大值。
我认为如果你不象征性地这样做,你会遇到奇怪的边缘情况。
您的角度范围不仅不能完全表示为二进制分数(引入舍入误差),而且是无理的。 (Pi
大于 3.14159265359 但小于 3.14159265360;除了符号之外,你怎么说角度等于Pi
/2?)
我认为最可靠的方法是依次获取所有区间组合,确定它们的交集,并查看这些组合区间中的哪些是大多数单个区间的交集的结果。
这也有一个好处,即为您提供的不仅仅是一个,而是满足您条件的所有角度。
- 为什么大多数 pair 实现默认不使用压缩(空基优化)?
- 使(虚拟)函数在大多数派生类中无法访问中间基类中可访问,定义良好?
- 大多数基本类型的高效二进制序列化
- 推断大多数模板对象的参数,但在调用模板函数时对其他对象显式
- boost::spirit--试图编译大多数简单代码的编译器错误
- 如何避免大多数成员功能相同的代码重复
- 大多数代码不仅显示欢迎消息和"enter pin"?
- 为什么不调用虚拟基非默认构造函数,除非大多数派生基显式调用它们?
- 是否有理由大多数/所有 try-catch 示例只对 throw 语句使用 void 子函数
- 大多数人代码中的ONLINE_JUDGE是什么?
- 在网格中找到大多数K移动和最高分数的路径
- 如果未实现虚函数,则大多数派生类无法编译,但如果一个基类未实现虚函数,则可以编译
- 大多数内存有效的方法是在C 中转置大文件
- 大多数令人烦恼的解析,并访问阵列
- 连接四个成功的组合检查适用于大多数情况,但不适用于某些情况
- 为什么大多数STL算法都需要将排序数据作为输入
- C++优雅地预测大多数字符串数组
- 是否可以在VS中管理所有或大多数C++错误
- 找到位于大多数角度间隔中的角度
- 如何使我的功能通过大多数频繁以及如何处理空间来组织?C