【问题标题】:Find the length of the longest path in the matrix with the consecutive character along with its path找出矩阵中最长路径的长度,其中包含连续字符及其路径
【发布时间】:2020-01-18 13:51:06
【问题描述】:

给定 M * N 个字符矩阵,找出从给定源开始的矩阵中最长路径的长度。

注意:最长路径中的所有字符都应该增加并且 按字母顺序相互连续。我们是 允许在所有 8 个方向搜索下一个字符。

我已经正确地找出了序列的长度,但是路径有问题。路径不正确。
这是我的代码

#include<iostream>
#include<vector>
using namespace std;

//Below array details all 8 posible directions
int row[] = { -1,-1,-1, 0, 0, 1, 1, 1 };
int col[] = { 1, 0, -1, 1,-1, -1,0, 1 };


int length(char arr[][5], int x, int y, char previous, vector<pair<int,int> > &path, int k)
{
    // x and y must be bounded between 0 to 4
    if( x < 0  || x > 4 || y > 4 || y < 0)
       return 0;

    int l = 0;
    int max_length = 0;

    for( int i = 0; i < 8; i++)
    {
        // storing next character in search
        char ch = arr[x+row[i]][y+col[i]];

        //checking whether ch is the next character in the sequence or not
        if(ch == previous + 1)
        {  
            //if k != path.size() then we have taken back in
            // the sequence so no need to push back character in the path
            if(k == path.size())
              {
                // Pushing co-ordinates of next valid character
                path.push_back(make_pair(x+row[i], y+col[i]));
              }
            else
                path.pop_back();

            l = 1 + length(arr, x+row[i], y+ col[i], ch , path, ++k);
            max_length = max( l, max_length);
        }

    }

    return max_length;
}

int main()
{
    char arr[5][5] = { 
                      { 'd','e','h','x','b'},
                      { 'a','o','g','p','e'},
                      { 'd','d','c','f','d'},
                      { 'e','b','e','a','s'},
                      { 'c','d','y','e','n'}
                    };
    vector<pair<int,int> > path;

    //Pusing source address
    path.push_back(make_pair(2,2));

    int k = 1;

    int Len = length(arr, 2, 2 , arr[2][2], path, k);

    cout << "Length of the Longest sequence is : " << Len + 1 <<endl; 

    //printing the path
    cout << "Path is : "<<endl;
    for( pair<int,int> i : path)
    {
        cout <<"( " << i.first <<","<<i.second <<" )" ;
    }

    return 0;
}

实际输出:

最长序列的长度为:6
路径是
( 2,2 )( 2,1)( 3,0 )( 3,2 )( 2,3 )( 1,2 )( 0,2 )

预期输出

最长序列的长度为:6
路径是
( 2,2 )(2,1 )( 3,2 )( 2,3 )( 1,2 )( 0,2 )

我的输出中有一个额外的 (3,0)。当我从 (3,0) 取回时,我无法弹出它。
任何帮助将不胜感激。

【问题讨论】:

  • (3,0) 来自哪里?您是否尝试使用调试器逐行执行代码?

标签: c++ algorithm c++11


【解决方案1】:

构建路径的算法不能这样工作。回溯时你有一些预知不破坏路径,但是当回溯之后——搜索再次向另一个方向加深时,路径将成为两条路径的组合:前一个分支不会从中删除。

所以在你的实际情况下,第一次尝试是从 (2,1) 到 (3,0)。在那里它发现它不能再深入了,但它是迄今为止最好的路径。然后它回溯到(2,1)。路径没有缩短(因为它仍然是最好的)。然后搜索再次加深到 (3,2)。然后将该地址添加到路径中,从而使其不一致。

它不能那样工作。当你找到一条更好的路径时,你需要创建一条新路径,并确保它永远不会再被改变。只有当你找到更好的路径时,你才完全替换它。

我还建议限制函数的参数(++k 也是一个问题——但我们可以不这样做)。让函数返回最长的路径,而不是改变路径参数。长度总是可以从中推导出来的。

所以这里是你的函数可以如何修改:

#include<iostream>
#include<vector>
using namespace std;

//Below array details all 8 posible directions
int row[] = { -1,-1,-1, 0, 0, 1, 1, 1 };
int col[] = { 1, 0, -1, 1,-1, -1,0, 1 };

vector<pair<int,int> > longestPath(char arr[][5], int x, int y)
{
    char previous = arr[x][y];
    vector<pair<int,int> > path; // a new(!) path
    // x and y must be bounded between 0 to 4
    if( x < 0  || x > 4 || y > 4 || y < 0)
       return path;

    for (int i = 0; i < 8; i++)
    {
        // storing next character in search
        char ch = arr[x+row[i]][y+col[i]];

        //checking whether ch is the next character in the sequence or not
        if(ch == previous + 1)
        {  
            vector<pair<int,int> > foundPath = longestPath(arr, x+row[i], y+ col[i]);
            if (foundPath.size() > path.size())
                path = foundPath;
        }

    }
    path.insert(path.begin(), make_pair(x,y));
    return path;
}

int main()
{
    char arr[5][5] = { 
                      { 'd','e','h','x','b'},
                      { 'a','o','g','p','e'},
                      { 'd','d','c','f','d'},
                      { 'e','b','e','a','s'},
                      { 'c','d','y','e','n'}
                    };
    vector<pair<int,int> > path = longestPath(arr, 2, 2);

    //printing the path
    cout << "Path is : "<<endl;
    for( pair<int,int> i : path)
    {
        cout <<"( " << i.first <<","<<i.second <<" )" ;
    }

    return 0;
}

【讨论】:

    【解决方案2】:

    与其从实现开始并向我们展示 - 您应该从抽象算法(和数据结构)开始,并尽最大努力确保是合理的。另外,我建议不要过多关注单个指令和循环变量的序列,而是关注它的全局。

    所以,这是一个相对幼稚的算法:

    • 为(潜在)路径中的每个节点运行一个阶段:因此,在您的情况下,最多 26 个阶段。
    • 在每个阶段,您都持有路径可以到达的矩阵位置集;然后你推导出这些路径可以通过另一个步骤到达的位置集。换句话说,您正在推进一条多条道路的“前沿”,一次一步。
    • 相位动作可以通过尝试从每个前面的位置向前移动来实现(例如,检查前面的哪个 'f' 有一个相邻的 'g');或者通过尝试从具有适当相位值的每个矩阵元素向后移动(例如,搜索矩阵中的哪些 g 与前一个前面的 f 相邻。)

    这与您的方法不同,因为在各个路径上没有递归。这种递归可能会很快爆发。虽然您的路径确实不能超过 26 个字符,但原则是有问题的。假设您有一个如下所示的对角矩阵:

    abcde  ...
    bcde  ...
    cde  ...
    de ...
    e ...
    .
    .
    .
    

    左右移动的任意组合都是有效路径;所以从 a 开始有 2^k 条长度为 k 的路径。你想调用你的longestPath() 2^26 次吗?如果你不必... :-(

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-09
      • 2019-11-04
      • 1970-01-01
      • 2017-01-09
      • 2020-03-06
      相关资源
      最近更新 更多