📜  矩阵中回文路径的数量

📅  最后修改于: 2021-04-29 05:35:19             🧑  作者: Mango

给定一个仅包含较低字母字符的矩阵,我们需要计算给定矩阵中回文路径的数量。路径定义为从左上角的单元格开始到右下角的单元格结束的单元格序列。我们只能从当前单元格向右和向下移动。

例子:

Input : mat[][] = {"aaab”, 
                   "baaa”
                   “abba”}
Output : 3

Number of palindromic paths are 3 from top-left to 
bottom-right.
aaaaaa (0, 0) -> (0, 1) -> (1, 1) -> (1, 2) -> 
                                (1, 3) -> (2, 3)    
aaaaaa (0, 0) -> (0, 1) -> (0, 2) -> (1, 2) -> 
                                (1, 3) -> (2, 3)    
abaaba (0, 0) -> (1, 0) -> (1, 1) -> (1, 2) -> 
                                 (2, 2) -> (2, 3)    

回文矩阵

我们可以从回文路径的两个角(左上角和右下角)开始递归地解决此问题。在每个递归调用中,我们维持一个状态,该状态将组成两个单元,一个单元从起点开始,一个单元从终点开始,这对于回文性质应该是相等的。如果在一个状态下,两个单元格字符相等,则我们将在两个方向上进行所有可能的移动的递归调用。
由于这可能导致多次解决相同的子问题,因此我们在下面的代码中使用了一个地图备忘,该备忘录存储了以键为起点和终点的索引存储计算结果,因此如果再次调用具有相同起点和终点的子问题,结果将为由备忘直接返回,而不是重新计算。
请参阅下面的代码以更好地理解,

CPP
// C++ program to get number of palindrome
// paths in matrix
#include 
 
using namespace std;
 
#define R 3
#define C 4
 
// struct to represent state of recursion
// and key of map
struct cells
{
    //  indices of front cell
    int rs, cs;
 
    //  indices of end cell
    int re, ce;
    cells(int rs, int cs, int re, int ce)
        : rs(rs)
        , cs(cs)
        , re(re)
        , ce(ce)
    {
    }
 
    // operator overloading to compare two
    // cells which rs needed for map
    bool operator<(const cells& other) const
    {
        return ((rs != other.rs) || (cs != other.cs)
                || (re != other.re) || (ce != other.ce));
    }
};
 
// recursive method to return number
//  of palindromic paths in matrix
// (rs, cs) ==> Indices of current cell
//              from a starting point (First Row)
// (re, ce) ==> Indices of current cell
//              from a ending point (Last Row)
// memo     ==> To store results of
//              already computed problems
int getPalindromicPathsRecur(char mat[R][C],
                             int rs, int cs,
                             int re, int ce,
                             map& memo)
{
    // Base Case 1 : if any index rs out of boundary,
    // return 0
    if (rs < 0 || rs >= R || cs < 0 || cs >= C)
        return 0;
    if (re < 0 || re < rs || ce < 0 || ce < cs)
        return 0;
 
    // Base case 2 : if values are not equal
    // then palindrome property rs not satisfied,
    // so return 0
    if (mat[rs][cs] != mat[re][ce])
        return 0;
 
    // If we reach here, then matrix cells are same.
 
    // Base Case 3 : if indices are adjacent then
    // return 1
    if (abs((rs - re) + (cs - ce)) <= 1)
        return 1;
 
    //  if result rs precalculated, return from map
    if (memo.find(cells(rs, cs, re, ce))
        != memo.end())
        return memo[cells(rs, cs, re, ce)];
 
    int ret = 0; // Initialize result
 
    // calling recursively for all possible movements
    ret += getPalindromicPathsRecur(mat, rs + 1,
                                    cs, re - 1,
                                    ce, memo);
    ret += getPalindromicPathsRecur(mat, rs + 1,
                                    cs, re,
                                    ce - 1, memo);
    ret += getPalindromicPathsRecur(mat, rs,
                                    cs + 1, re - 1,
                                    ce, memo);
    ret += getPalindromicPathsRecur(mat, rs,
                                    cs + 1, re,
                                    ce - 1, memo);
 
    // storing the calculated result in map
    memo[cells(rs, cs, re, ce)] = ret;
 
    return ret;
}
 
//  method returns number of palindromic paths in matrix
int getPalindromicPaths(char mat[R][C])
{
    map memo;
    return getPalindromicPathsRecur(mat, 0, 0, R - 1, C - 1,
                                    memo);
}
 
//  Driver code
int main()
{
    char mat[R][C] = { 'a', 'a', 'a',
                      'b', 'b', 'a',
                       'a', 'a', 'a',
                      'b', 'b', 'a' };
    printf("%d", getPalindromicPaths(mat));
 
    return 0;
}


输出
3

时间复杂度: O((R x C) 2 )