c++ - 连通分量程序产生不正确的输出

标签 c++ c++11 recursion graph connected-components

我正在开发一个程序,它接受一个 5x5 字符数组并找到最长的相同字符列表,连接意味着相邻的上、下、左或右(意味着没有对角线)。然而,输出偏移 1,给出 6 而不是正确的 7,输入:

a b c c b
a c b c c
c a a b a
b b a a c
a a a b a

谁能帮我找出我代码中的错误是什么? (我的代码在下面)

详细信息:缺少的字符位于索引 [3][3](索引从 0 开始)。当我测试我的 look() 函数时,它工作正常,当我为行传递 3,为 col 传递 2 时,它添加了 [3][3] 到要返回的最终 vector ,但是我认为递归没有成功。

我已经对此进行了调试,但没有成功,您可以在我的代码中看到调试打印。

#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <utility>

using namespace std;
char grid[5][5];
bool seen[5][5];
int cnt = 1;
int maxn = 0;

vector<pair<int, int>> look(int row, int col)
{
    //
    vector<pair<int, int >> node_list;
    if (row != 0)
        if (grid[row - 1][col] == grid[row][col])
            if (!seen[row - 1][col])
                node_list.push_back(make_pair(row - 1, col));
    if (row != 4)
        if (grid[row + 1][col] == grid[row][col])
            if (!seen[row+1][col])
                node_list.push_back(make_pair(row + 1, col));
    if (col != 0)
        if (grid[row][col - 1] == grid[row][col])
            if (!seen[row][col-1])
                node_list.push_back(make_pair(row, col - 1));
    if (col != 4)
        if (grid[row][col + 1] == grid[row][col])
            if (!seen[row][col+1])
                node_list.push_back(make_pair(row, col + 1));
    if (binary_search(node_list.begin(), node_list.end(), make_pair(2, 2)))
        cout << "HAPPENED^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" << "\n";
    return node_list;
}

void search(int row, int col)
{
    for (pair<int, int> a : look(row, col))
    {
        if (!seen[a.first][a.second])
        {
            seen[a.first][a.second] = true;
            cnt++;
            cout << "COUNTED and now SEARCHING " << a.first << " " << a.second << "\n";
            cout << "search about to be called on " << a.first << " " << a.second << "\n";
            search(a.first, a.second);
        }
    }
    if (cnt > maxn)
        maxn = cnt;
    cout << "CNT: " << cnt << "\n";
    cnt = 1;
    return;
}

int main()
{
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            cin >> grid[i][j];
            seen[i][j] = false;
        }
    }

    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            if (!seen[i][j])
            {
                cout << "INITIALLY SEARCHING: " << i << " " << j << "\n";
                seen[i][j] = true;
                cout << "search about to be called on " << i << " " << j << "\n";
                search(i, j);
            }
            else
                cout << "NO INITIAL SEARCH, SEEN: " << i << " " << j << "\n";
        }
    }
    cout << maxn << "\n";
    return 0;
}

最佳答案

问题是您正在递归地使用 search,但也在其末尾无条件地重置 cnt

这个问题可以在一个只有 3 个字符的简单“板”上演示:

a a a

假设我们从中间的a开始search。它调用 look 并被告知检查另外两个地方:左边的 a 和右边的 asearch 然后调用自己,比方说用左边的 acnt 此时是 2 并且左边和中间的 a 都将它们的 seen 设置为 true 。这第二次递归 search 调用再次要求 look 找到附近的 a,但这次它们都已经看到了。所以第二个 search 完成,将 maxn 设置为 2 并将 重置 cnt1 。现在我们回到递归的第一层,继续处理右边的a。不用说,我们已经丢弃了一次在左边计算 a 的次数。

这里的问题是你没有明确区分“递归搜索附近的字段”和“从这一点开始搜索”。您当前 search 的最后两行属于后者而不是前者。我建议这样做:

void searchRecursive(int row, int col)
{
    for (pair<int, int> a : look(row, col))
    {
        if (!seen[a.first][a.second])
        {
            seen[a.first][a.second] = true;
            cnt++;
            searchRecursive(a.first, a.second);
        }
    }
}

void startSearchFrom(int row, int col)
{
    cnt = 1;
    seen[i][j] = true;
    searchRecursive(row, col);
    if (cnt > maxn)
        maxn = cnt;
    cout << "CNT: " << cnt << "\n";
}

这很好地分离了这些问题。

进一步的改进是摆脱所有的全局状态。尽管 seen 从未被重置,但您的算法仍能正常工作并不是立即显而易见(尽管是真的),并且验证是否正确使用了 cnt 需要牢记 all 使用它的地方。如果每个 searchRecursive 都返回它找到了多少个看不见的位置,那么验证结果是否正确将是微不足道的。

关于c++ - 连通分量程序产生不正确的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51952537/

相关文章:

SQL:如何从递归查询创建 View ?

java - 使用洪水填充算法创建数组

c++ - 为什么 MSCVRT 库会在链接时产生冲突?

c++ - 虚拟继承 : what happens if the keyword is at some point forgotten?

c++ - 起源 - 不变的还是新的类型?

python - 递归组合字典

c++ - 为什么 const_iterator 可以与 std::map::erase 一起使用

c++ - 要求用户制造的容器符合 range-v3

multithreading - std::thread::hardware_concurrency 是一个,我应该在我的系统上实现线程吗

c++ - 是否允许在 std::declval<T> 上使用 decltype (函数本身,而不是调用它的结果)?