在2D表中查找匹配项

时间:2016-05-02 15:38:13

标签: c++ algorithm match eigen

假设我有一个Eigen :: MatrixXf(4,5),没有重复,如下所示:

    a      b    c     d     e
A: 0.60  0.70  0.80  0.90  0.00
B: 0.51  0.61  0.71  0.81  0.91
C: 0.41  0.31  0.21  0.11  0.01
D: 0.10  0.20  0.30  0.40  0.50

我需要找到row(i)和column(j)之间的匹配,其中值(i,j)是较小的(最小的最小值)1,而(i)或(j)只选择一次。

我的方法结果:

我的工作让我从左上角到右下角开始一个(微不足道的)迭代方法,并搜索最小的匹配,到目前为止,我得到了夫妻(A,e =0.00) (B,a =0.51) (C,e =0.01) (D,a =0.10)

    a      b    c     d     e
A: 0.60  0.70  0.80  0.90  0.00
                             ^
B: 0.51  0.61  0.71  0.81  0.91
     ^
C: 0.41  0.31  0.21  0.11  0.01
                             ^
D: 0.10  0.20  0.30  0.40  0.50
     ^

通缉结果

所以,正如你所看到的,我得到'e'和'a'两次匹配,这是不可取的。我完美的匹配将改为(A,e =0.00) ( D,a =0.10) (C,d =0.11) (B,b =0.61)而留下'c'无法比拟。

    a      b    c     d     e
A: 0.60  0.70  0.80  0.90  0.00
                             ^
B: 0.51  0.61  0.71  0.81  0.91
           ^
C: 0.41  0.31  0.21  0.11  0.01
                       ^
D: 0.10  0.20  0.30  0.40  0.50
     ^

必须有办法做到这一点,但我无法理解!

这是我的代码:

for (i = 0; i < Score.rows(); i++)
{
    Correspondance correspondence;
    correspondence.source = source[i];
    int idx = 0;
    for (int j = 0; j < Score.cols(); j++)
    {
        if (Score(i, j) < Score(i, idx)) idx = j;
    }
    correspondence.target = target[idx];
    correspondences_.push_back(correspondence);
}

 with Source [A, B, C, D] and target [a, b, c, d, e]

2 个答案:

答案 0 :(得分:1)

我有点把它作为一个挑战,写下我可能会做的事情来解决你的问题。 (使用C ++ 11功能)

#include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>

double data[4][5] = { 
    { 0.60, 0.70, 0.80, 0.90, 0.00 },
    { 0.51, 0.61, 0.71, 0.81, 0.91 },
    { 0.41, 0.31, 0.21, 0.11, 0.01 },
    { 0.10, 0.20, 0.30, 0.40, 0.50 } };

struct Element
{
    int x;
    int y;
    double value;
};

std::vector<Element> find(double (&matrix)[4][5])
{
    std::vector<Element> elements;
    std::vector<Element> matches;

    // build vector of all elements
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 5; j++)
            elements.push_back({i, j, matrix[i][j]});

    // sort all elements from smallest to largest
    std::sort(elements.begin(), elements.end(), 
    [](const Element& a, const Element& b)
    {
       return a.value < b.value;
    });

    while (!elements.empty())
    {
        // pull out smallest value
        Element smallest = elements[0];
        matches.push_back(smallest);

        // remove all other elements in the same row or column
        elements.erase(std::remove_if(elements.begin(), elements.end(), 
        [smallest](const Element& e)
        {
            return e.x == smallest.x || e.y == smallest.y;
        }), elements.end());
    }

    return matches;
}

int main()
{
    auto matches = find(data);

    // print values
    for (auto match : matches)
        std::cout << "("   << match.x 
                  << ","   << match.y 
                  << " = " << match.value 
                  << ")"   << std::endl;

    return 0;
}

答案 1 :(得分:0)

以下是我的理解: 您正在搜索每行中的唯一最小值。并且您希望按顺序(从最小到最大)找到最小值。

这意味着您无法像现在一样逐行搜索。您需要搜索ENTIRE表4次以查找每行的最小值。在您成功找到某些内容后,请删除您找到的行和列,以便它不会再次搜索。

我提供了两个想法,用于删除已经找到的行/列。它们在下面的代码中标记为选项1和选项2。 ;)

//search for 4 values
for (i = 0; i < Score.rows(); i++)
{
    //search ALL rows
    for (i = 0; i < Score.rows(); i++)
    {
        Correspondance correspondence;
        correspondence.source = source[i];
        int idx = 0;
        for (int j = 0; j < Score.cols(); j++)
        {
            //OPTION 1: Do something here to reject indexes from row/col that are already "found"
            if (Score(i, j) < Score(i, idx)) idx = j;
        }       
    }
    //only record the answer after all rows are searched
    //this is the global minimum value
    correspondence.target = target[idx];
    correspondences_.push_back(correspondence);
    //OPTION 2: Do something here to eliminate the row/cols that are already "found" so that they don't get searched again
}

P.S。我不知道C ++中的通信是什么,所以我将它视为一个数组问题,其中push / pop是一个选项