在2D表格中查找匹配项

finding matches in 2D table

本文关键字:查找 2D 表格      更新时间:2023-10-16

假设我有一个特征::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

我需要找到行(I)和列(j)之间的匹配,其中值(I,j)较小(最小值中的最小值),其中(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"answers"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]

我觉得这是一个挑战,并写下了我可能会做些什么来解决你的问题。(使用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;
}

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

这意味着你不能像现在这样逐行搜索。您需要在ENTIRE表中搜索4次,才能找到每行的最小值。在你成功地找到某个东西后,去掉你找到的行和列,这样它就不会再次被搜索。

我包含了两个去除已经找到的行/列的想法。在下面的代码中,它们被标记为OPTION 1和OPTION 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
}

附言:我不知道C++中的对应关系是什么,所以我把它当作一个数组问题来处理,其中push/pop是一个选项