【问题标题】:How to be faster while deleting vector row?删除向量行时如何更快?
【发布时间】:2013-05-16 17:32:53
【问题描述】:

这对我想做的事情来说太长了。 有什么办法可以加快速度?

编辑抱歉,我一直遇到质量邮政编码问题,所以我只发布了最低限度。

我想做的是一个奥马哈扑克净值计算器。

A-它需要我们给他的 4 张牌(myhand[4]),然后检查所有可能的手牌组合,看看是否有任何重复。

B-如果有任何重复,它想删除包含那只手的向量的行 (所以当我们稍后计算胜率时,我们不会针对某人不可能拥有的牌进行计算)

int myhand[4] = { 3, 12, 22, 10 };
    vector<vector<int> > vec(4, vector<int>(270725));
    for (int m = 0; m < vec[0].size(); m++) { // A
        for (int k = 0; k < 4; k++) {
            for (int j = 0; j < 4; j++)
                if (myhand[k] == vec[j][m]) {
                    for (int i = 0; i < 4; i++) {
                        vec[i].erase(vec[i].begin() + m); // B
                    }
                    k = 0;
                    j = 0;
                    break;
                }
        }
    }

有没有办法提高这段代码的效率?

谢谢, 卡文

【问题讨论】:

  • 这一切有什么意义?了解代码应该在高层次上实现什么以了解如何最好地优化它会非常有用。
  • 看起来很奇怪... 4个for循环看起来有点矫枉过正
  • 转置矩阵可能会提高性能。
  • 270725 已经是 52 个无序的 4 个。所以你至少不需要 size() = 270725 但 size() = 52 的 4 个 vec。顺便说一句 - 你的内部向量只是保持零,这不是你需要的。
  • 这是不是运行太慢了?如果不是,我们为什么要玩它? :)

标签: c++ performance vector


【解决方案1】:

在像 std::vector 这样的非关联容器上搜索太昂贵了。

std::set 如果只找到 Hands 就可以了,但是就问题域而言,所讨论的键是复合键(卡片的 4 元组),并且 std::set 没有特殊方法处理类似的事情

“查找包含某个组件的所有键。”

std::map 也只能解决一部分问题。

boost::bimap 可以考虑,但我提出了不同的方法:


问题的数据可以通过二分图建模(左手牌,右手右手,lr 边表示从“卡片顶点”看“​​在手”,如果从“手”顶点看,“包含卡片” ”。

因此,我更喜欢使用(基于 STL 的)boost::graph,而不是基于自编码 STL 的解决方案。


另一种实用的方法是依赖内存数据库,该数据库可以使用 SQLite 轻松创建;请参加 http://www.sqlite.org/inmemorydb.html

【讨论】:

    【解决方案2】:

    你最好通过一个看起来像这样的循环来构造你想要处理的组合:

    #include <cassert>
    #include <algorithm>
    #include <vector>
    #include <iostream>
    #include <numeric>
    
    int main (int, char* [])
    {
        // Build a deck of cards
        std::vector<int> deck( 52 );
        std::iota( deck.begin(), deck.end(), 0 );
    
        // Remove 'myhand'
        const int myhand[] =  { 3, 12, 22, 10 };
        for (int i = 0; i < 4; ++i) {
            deck[myhand[i]] = -1;
        }
        deck.resize( std::remove( deck.begin(), deck.end(), -1 ) - deck.begin() );
    
        // Iterate over all possible remaining entries.
        size_t num_processed = 0;
        for (auto c1 = deck.begin(); c1 != deck.end(); ++c1) {
            for (auto c2 = c1 + 1; c2 != deck.end(); ++c2) {
                for (auto c3 = c2 + 1; c3 != deck.end(); ++c3) {
                    for (auto c4 = c3 + 1; c4 != deck.end(); ++c4) {
                        // Compute equity of (*c1, *c2, *c3, *c4) here.
    
                        ++num_processed;
                    }
                }
            }
        }
        // Verify that 48! / (44! * 4!) entries were processed.
        assert ( num_processed == (48*47*46*45) / (4*3*2*1) );
        return 0;
    }
    

    顺便说一句,我写了一个德州扑克净值计算器。

    【讨论】:

    • 我正在做的事情很像这样,但我不能生成这样的随机牌,因为如果我想在翻牌前根据特定范围(%)进行计算,我必须尊重一定的手牌排名。我将尝试将其调整为我的代码。非常感谢。
    【解决方案3】:

    尝试根据我的理解回答。

    myhand[k] == vec[j][m] 时,您正在制作 k=0。它打破了 j for 循环。

    但是 k for 循环又从零重新开始了。

    如果它再次匹配条件myhand[k] == vec[j][m],它会继续。

    除此之外,请考虑使用std::find 算法,而不是编写循环等。

    【讨论】:

      猜你喜欢
      • 2016-07-04
      • 2010-11-11
      • 2023-02-03
      • 1970-01-01
      • 1970-01-01
      • 2018-07-14
      • 2021-06-11
      • 2023-03-11
      • 2013-04-07
      相关资源
      最近更新 更多