【问题标题】:std map constructing strict weak order and finding lower boundstd map 构造严格的弱顺序并找到下限
【发布时间】:2020-10-20 12:15:16
【问题描述】:

我有一些现实生活中的墙,其特点是两个高度(最左边和最右边的高度)。

例如

I        I     I  I
I     I  I     I  I
I     I  I     I  I    I
I_____I  I_____I  I____I

第一个有最左边的高度hl=4,最右边的高度hr=3,第二个有hl=4hr=4等等。

鉴于hlhr,我现在的任务是找到体积最小的墙以达到hlhr。所以 (a) 只允许降低墙两侧的高度,但不能增加,(b) 损失的体积应该是最小的。

在第一种方法中,我使用最小高度hMin=std::min(hl,hr) 将问题降低到一个高度。通过这样做,我可以用“墙”填充地图并使用hMin 作为键,然后使用lower_bound 搜索max(hl,hr) 来获得解决方案。

现在考虑到两个高度的最佳解决方案,我在构建严格的弱顺序时遇到了各种麻烦。到目前为止,我尝试将键扩展到第二个高度,使用自定义的 less 并等效地使用 lower_bound。 我的自定义 less 看起来有点像:

    struct KeyLess
    {
        bool operator(Key const&x, Key const&y) const
        {
            if ((x.hl + roundOff < y.hl ) && (x.hr+ roundOff < y.hr))
                return true;
            if ((y.hl + roundOff < x.hl ) && (y.hr+ roundOff < x.hr))
                return false;
            return false;
        }
    };

但对于x.hl&gt; y.hlx.hr &lt; y.hr 或这些类型在视觉上显然存在问题

I              I  
I              I  I    I
I     I  I     I  I    I
I_____I  I_____I  I____I

并且没有给出严格的弱排序afaik。

如果能为我的问题构建一个 less 运算符或向我展示另一种解决此问题的方法,我将不胜感激。


例子

I              I       I  I        I     I
I              I  I    I  I     I  I     I
I              I  I    I  I     I  I     I
I     I        I  I    I  I     I  I     I
I_____I  I_____I  I____I  I_____I  I_____I

给定 hl=3hr=5 它应该返回第三个(hl=4hr=5)。 只要我能找到解决方案,墙壁在地图中保存的顺序本身并不相关(但我认为这也是我在这里找到有意义的顺序的问题)。

【问题讨论】:

  • 不相关:operator&lt; 有效地做:return ((x.hl + roundOff &lt; y.hl ) &amp;&amp; (x.hr+ roundOff &lt; y.hr)); 所以你可以用它替换函数的主体。您能举一些例子吗?您希望按什么顺序对结果进行排序?
  • 我不明白你的问题描述。但这听起来像是一个组合问题,而不是排序问题(即不能简单地通过排序来解决)。
  • 请查看更新后的问题(包括示例)。谢谢
  • 您拥有的是部分订单,而不是全订单。
  • 如果顺序无关紧要,为什么不使用 unordered_set 或 std::tie?

标签: c++ stdmap


【解决方案1】:

我想你想要

struct KeyLess
{
    bool operator(Key const&x, Key const&y) const
    {
        return std::pair(std::abs(x.hl - x.hr), std::min(x.hl, x.hr)) 
             < std::pair(std::abs(y.hl - y.hr), std::min(y.hl, y.hr));
    }
};

即首先按高度差排序,然后按较小的高度排序。如果还需要区分

      I  I        
      I  I        
I     I  I     I  
I_____I  I_____I  

然后你可以通过任意选择第一个小于第二个来扩展它

struct KeyLess
{
    bool operator(Key const&x, Key const&y) const
    {
        return std::tuple(std::abs(x.hl - x.hr), std::min(x.hl, x.hr), x.hl < x.hr) 
             < std::tuple(std::abs(y.hl - y.hr), std::min(y.hl, y.hr), y.hl < y.hr);
    }
};

【讨论】:

  • 如果我没记错的话,这并没有通过使用 lower_bound 来提供最小的损失墙(或者是这样吗?)。然后我将如何使用此排序找到最小损失墙?
  • @ezegoing 是“最小损失”std::abs(x.hl - x.hr)?切换元素的顺序优先。我不确定为什么它不是您示例中的第 5 个元素
  • 我的损失可以简化为y.hl-x.hl + y.hr-x.hr 假设y.hl &gt;= x.hly.hr &gt;= x.hr
【解决方案2】:

您有一个需要严格弱排序的地图(或集合),但您不关心顺序。

您可以简单地使用 unordered_map(或 unordered_set)而不必担心。

或者您可以创建严格的弱排序。幸运的是,标准库中已经可以使用 #include

中的 std::tie
bool Key::operator<(const Key &rhs) const {
    return std::tie(hl, hr) < std::tie(rhs.hl, rhs.hr);
}

当然,如果顺序确实很重要,但有其自身的含义并且可以任意更改,那么您应该使用 std::vector。让算法把东西放在需要的地方。

【讨论】:

  • 我很困惑你是如何声明课程的,或者你为什么说 KeyLess。如果您不想要密钥,请使用集合。
  • 好吧,对不起。如果您想到只有一个高度的问题,那么使用某种排序(例如使用 map 和 asc.)显然是有意义的 i.o.使用 lower_bound 轻松高效地获得解决方案。也就是说,订单对我来说并不重要,但我可以通过某种方式轻松获得结果。当我将其扩展到两个高度时,这就是我的想法。
  • 如果比较运算符要为您提供最终输出,这将需要明确的规则和您的代码,以及失败的输入、实际和预期的输出。而且它要做的不仅仅是严格的弱排序——它必须是实际的解决方案算法(仅通过排序规则可能会也可能不会)。
猜你喜欢
  • 1970-01-01
  • 2013-02-14
  • 1970-01-01
  • 1970-01-01
  • 2012-11-14
  • 2018-08-04
  • 2010-11-20
  • 2021-12-04
  • 1970-01-01
相关资源
最近更新 更多