2

这对我想做的事情来说太长了。有什么办法可以让这更快吗?

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

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

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

3 回答 3

1

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

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

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

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

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


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

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


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

于 2013-05-16T23:13:12.093 回答
0

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

#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;
}

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

于 2013-05-16T18:24:53.207 回答
0

试图从我的理解中回答。

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

但是 k for 循环再次从零重新开始。

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

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

于 2013-05-16T17:58:45.737 回答