📌  相关文章
📜  矩阵中从左上角到右下角的字典序最大素数路径

📅  最后修改于: 2021-09-17 07:47:05             🧑  作者: Mango

给定一个mxn正整数矩阵。任务是找到从矩阵左上角到矩阵右下角的路径数,使得路径中的每个整数都是素数。
另外,打印所有路径中字典序最大的路径。单元格 (a, b) 在字典序上比单元格 (c, d) 大,要么 a > b,要么如果 a == b 则 b > d。从单元格 (x, y),您可以移动 (x + 1, y), (x, y + 1), (x + 1, y + 1)。

注意:假设左上角的单元格总是有一个质数。

例子:

方法:思路是使用动态规划来解决问题。首先,观察,矩阵中的非质数可以被视为障碍,质数可以被视为可以在路径中使用的单元格。因此,我们可以使用筛子来识别障碍物,并将给定的矩阵转换为二进制矩阵,其中 0 表示障碍物,1 表示有效路径。
因此,我们将定义一个二维矩阵,比如 dp[][],其中 d[i][j] 表示从单元格 (1, 1) 到单元格 (i, j) 的路径数。此外,我们可以将 dp[i][j] 定义为,

dp[i][j] = dp[i-1][j] + dp[i][j-1] + dp[i-1][j-1]

即从左单元格、右单元格和左上角对角线(允许移动)的路径总和。
为了找到字典序最大的路径,我们可以使用 DFS(深度优先搜索)。将每个单元格视为一个节点,该节点具有三个外向边,一条指向右邻单元格、下邻单元格和左下角单元格对角线。现在,我们将以某种方式使用深度优先搜索进行旅行,以便我们获得字典序最大的路径。因此,为了获得字典序最大的路径,我们首先尝试从单元格 (x, y) 前往单元格 (x + 1, y + 1)(如果该单元格没有可能的路径),然后尝试前往单元格 (x + 1, y) 最后到 (x, y + 1)。

下面是这个方法的实现:

C++
// C++ implementation of above approach
#include 
using namespace std;
#define MAX 105
 
void sieve(int prime[])
{
    for (int i = 2; i * i <= MAX; i++) {
        if (prime[i] == 0) {
            for (int j = i * i; j <= MAX; j += i)
                prime[j] = 1;
        }
    }
}
 
// Depth First Search
void dfs(int i, int j, int k, int* q, int n, int m,
         int mappedMatrix[][MAX], int mark[][MAX],
                                  pair ans[])
{
    // Return if cell contain non prime number or obstacle,
    // or going out of matrix or already visited the cell
    // or already found the lexicographical larget path
    if (mappedMatrix[i][j] == 0 || i > n
                         || j > m || mark[i][j] || (*q))
        return;
 
    // marking cell is already visited
    mark[i][j] = 1;
 
    // storing the lexicographical largest path index
    ans[k] = make_pair(i, j);
 
    // if reached the end of the matrix
    if (i == n && j == m) {
 
        // updating the final number of
        // steps in lexicographical largest path
        (*q) = k;
        return;
    }
 
    // moving diagonal (trying lexicographical largest path)
    dfs(i + 1, j + 1, k + 1, q, n, m, mappedMatrix, mark, ans);
 
    // moving cell right to current cell
    dfs(i + 1, j, k + 1, q, n, m, mappedMatrix, mark, ans);
 
    // moving cell down to current cell.
    dfs(i, j + 1, k + 1, q, n, m, mappedMatrix, mark, ans);
}
 
// Print lexicographical largest prime path
void lexicographicalPath(int n, int m, int mappedMatrix[][MAX])
{
    // to count the number of step in
    // lexicographical largest prime path
    int q = 0;
 
    // to store the lexicographical
    // largest prime path index
    pair ans[MAX];
 
    // to mark if the cell is already traversed or not
    int mark[MAX][MAX];
 
    // traversing by DFS
    dfs(1, 1, 1, &q, n, m, mappedMatrix, mark, ans);
 
    // printing the lexicographical largest prime path
    for (int i = 1; i <= q; i++)
        cout << ans[i].first << " " << ans[i].second << "\n";
}
 
// Return the number of prime path in ther matrix.
void countPrimePath(int mappedMatrix[][MAX], int n, int m)
{
    int dp[MAX][MAX] = { 0 };
    dp[1][1] = 1;
 
    // for each cell
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            // If on the top row or leftmost column,
            // there is no path there.
            if (i == 1 && j == 1)
                continue;
 
            dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]
                        + dp[i - 1][j - 1]);
 
            // If non prime number
            if (mappedMatrix[i][j] == 0)
                dp[i][j] = 0;
        }
    }
 
    cout << dp[n][m] << "\n";
}
 
// Finding the matrix mapping by considering
// non prime number as obstacle and prime number be valid path.
void preprocessMatrix(int mappedMatrix[][MAX],
                      int a[][MAX], int n, int m)
{
    int prime[MAX];
 
    // Sieve
    sieve(prime);
 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            // If prime
            if (prime[a[i][j]] == 0)
                mappedMatrix[i + 1][j + 1] = 1;
 
            // if non prime
            else
                mappedMatrix[i + 1][j + 1] = 0;
        }
    }
}
 
// Driver code
int main()
{
    int n = 3;
    int m = 3;
    int a[MAX][MAX] = { { 2, 3, 7 },
                        { 5, 4, 2 },
                        { 3, 7, 11 } };
 
    int mappedMatrix[MAX][MAX] = { 0 };
 
    preprocessMatrix(mappedMatrix, a, n, m);
 
    countPrimePath(mappedMatrix, n, m);
 
    lexicographicalPath(n, m, mappedMatrix);
 
    return 0;
}


Python3
# Python3 implementation of above approach
MAX = 105
  
def sieve():
     
    i = 2
     
    while(i * i < MAX):       
        if (prime[i] == 0):           
            for j in range(i * i,
                           MAX, i):           
                prime[j] = 1;       
        i += 1   
         
# Depth First Search
def dfs(i, j, k,
        q, n,  m):
 
    # Return if cell contain non
    # prime number or obstacle,
    # or going out of matrix or
    # already visited the cell
    # or already found the
    # lexicographical larget path
    if (mappedMatrix[i][j] == 0 or
        i > n or j > m or mark[i][j] or
        q != 0):
        return q;
  
    # marking cell is already
    # visited
    mark[i][j] = 1;
  
    # storing the lexicographical
    # largest path index
    ans[k] = [i, j]
  
    # if reached the end of
    # the matrix
    if (i == n and j == m):
  
        # updating the final number
        # of steps in lexicographical
        # largest path
        q = k;
        return q;
     
  
    # moving diagonal (trying lexicographical
    # largest path)
    q = dfs(i + 1, j + 1, k + 1, q, n, m);
  
    # moving cell right to current cell
    q = dfs(i + 1, j, k + 1, q, n, m);
  
    # moving cell down to current cell.
    q = dfs(i, j + 1, k + 1, q, n, m);
     
    return q
  
# Print lexicographical largest
# prime path
def lexicographicalPath(n, m):
 
    # To count the number of step
    # in lexicographical largest
    # prime path
    q = 0;
     
    global ans, mark
     
    # To store the lexicographical
    # largest prime path index
    ans = [[0, 0] for i in range(MAX)]
  
    # To mark if the cell is already
    # traversed or not
    mark = [[0 for j in range(MAX)]
               for i in range(MAX)]
  
    # traversing by DFS
    q = dfs(1, 1, 1, q, n, m);
  
    # printing the lexicographical
    # largest prime path
    for i in range(1, q + 1):
        print(str(ans[i][0]) + ' ' +
              str(ans[i][1]))
     
  
# Return the number of prime
# path in ther matrix.
def countPrimePath(n, m):
     
    global dp
     
    dp = [[0 for j in range(MAX)]
             for i in range(MAX)]
 
    dp[1][1] = 1;
  
    # for each cell
    for i in range(1, n + 1):
        for j in range(1, m + 1):
     
            # If on the top row or
            # leftmost column, there
            # is no path there.
            if (i == 1 and j == 1):
                continue;
  
            dp[i][j] = (dp[i - 1][j] +
                        dp[i][j - 1] +
                        dp[i - 1][j - 1]);
  
            # If non prime number
            if (mappedMatrix[i][j] == 0):
                dp[i][j] = 0;
     
    print(dp[n][m])   
  
# Finding the matrix mapping by
# considering non prime number
# as obstacle and prime number
# be valid path.
def preprocessMatrix(a, n, m):
     
    global prime
    prime = [0 for i in range(MAX)]
  
    # Sieve
    sieve();
     
    for i in range(n):
        for j in range(m):
         
            # If prime
            if (prime[a[i][j]] == 0):
                mappedMatrix[i + 1][j + 1] = 1;
  
            # if non prime
            else:
                mappedMatrix[i + 1][j + 1] = 0;
         
# Driver code
if __name__ == "__main__":
     
    n = 3;
    m = 3;
    a = [[ 2, 3, 7 ],
         [ 5, 4, 2 ],
         [ 3, 7, 11 ]];
     
    mappedMatrix = [[0 for j in range(MAX)]
                       for i in range(MAX)]
  
    preprocessMatrix(a, n, m);
  
    countPrimePath(n, m);
  
    lexicographicalPath(n, m);
  
# This code is contributed by Rutvik_56


C#
// C# implementation of above approach
using System;
using System.Collections;
using System.Collections.Generic;
 
class GFG{
 
static int MAX = 105;
  
static void sieve(int []prime)
{
    for(int i = 2; i * i < MAX; i++)
    {
        if (prime[i] == 0)
        {
            for (int j = i * i; j < MAX; j += i)
                prime[j] = 1;
        }
    }
}
 
class pair
{
    public int first,second;
     
    public pair(int first, int second)
    {
        this.first = first;
        this.second = second;
    }
}
  
// Depth First Search
static void dfs(int i, int j, int k,
            ref int q, int n, int m,
                int [,]mappedMatrix,
                int [,]mark, pair []ans)
{
     
    // Return if cell contain non prime
    // number or obstacle, or going out
    // of matrix or already visited the
    // cell or already found the
    // lexicographical larget path
    if ((mappedMatrix[i, j] == 0 ? true : false) ||
                          (i > n ? true : false) ||
                          (j > m ? true : false) ||
                (mark[i, j] != 0 ? true : false) ||
                         (q != 0 ? true : false))
        return;
  
    // Marking cell is already visited
    mark[i, j] = 1;
     
    // Storing the lexicographical
    // largest path index
    ans[k] = new pair(i, j);
     
    // If reached the end of the matrix
    if (i == n && j == m)
    {
         
        // Updating the final number of
        // steps in lexicographical
        // largest path
        (q) = k;
        return;
    }
     
    // Moving diagonal (trying
    // lexicographical largest path)
    dfs(i + 1, j + 1, k + 1, ref q,
        n, m, mappedMatrix, mark, ans);
  
    // Moving cell right to current cell
    dfs(i + 1, j, k + 1, ref q,
        n, m, mappedMatrix, mark, ans);
  
    // Moving cell down to current cell.
    dfs(i, j + 1, k + 1, ref q,
        n, m, mappedMatrix, mark, ans);
}
  
// Print lexicographical largest prime path
static void lexicographicalPath(int n, int m,
                                int [,]mappedMatrix)
{
     
    // To count the number of step in
    // lexicographical largest prime path
    int q = 0;
     
    // To store the lexicographical
    // largest prime path index
    pair []ans = new pair[MAX];
  
    // To mark if the cell is already
    // traversed or not
    int [,]mark = new int[MAX, MAX];
  
    // Traversing by DFS
    dfs(1, 1, 1, ref q, n,
        m, mappedMatrix, mark, ans);
  
    // Printing the lexicographical
    // largest prime path
    for(int i = 1; i <= q; i++)
        Console.WriteLine(ans[i].first + " " +
                          ans[i].second);
}
  
// Return the number of prime
// path in ther matrix.
static void countPrimePath(int [,]mappedMatrix,
                           int n, int m)
{
    int [,]dp = new int[MAX, MAX];
     
    for(int i = 0; i < MAX; i++)
    {
        for(int j = 0; j < MAX; j++)
        {
            dp[i, j] = 0;
        }
    }
     
    dp[1, 1] = 1;
  
    // For each cell
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
             
            // If on the top row or leftmost
            // column, there is no path there.
            if (i == 1 && j == 1)
                continue;
  
            dp[i, j] = (dp[i - 1, j] + dp[i, j - 1] +
                        dp[i - 1, j - 1]);
  
            // If non prime number
            if (mappedMatrix[i, j] == 0)
                dp[i, j] = 0;
        }
    }
    Console.WriteLine(dp[n, m]);
}
  
// Finding the matrix mapping by considering
// non prime number as obstacle and prime
// number be valid path.
static void preprocessMatrix(int [,]mappedMatrix,
                             int [,]a, int n, int m)
{
    int []prime = new int[MAX];
     
    // Sieve
    sieve(prime);
  
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
             
            // If prime
            if (prime[a[i, j]] == 0)
                mappedMatrix[i + 1, j + 1] = 1;
  
            // If non prime
            else
                mappedMatrix[i + 1, j + 1] = 0;
        }
    }
}
  
// Driver code
public static void Main(string []args)
{
    int n = 3;
    int m = 3;
    int [,]a = new int[3, 3]{ { 2, 3, 7 },
                              { 5, 4, 2 },
                              { 3, 7, 11 } };
  
    int [,]mappedMatrix = new int[MAX, MAX];
     
    for(int i = 0; i < MAX; i++)
    {
        for(int j = 0; j < MAX; j++)
        {
            mappedMatrix[i, j] = 0;
        }
    }
     
    preprocessMatrix(mappedMatrix, a, n, m);
  
    countPrimePath(mappedMatrix, n, m);
     
    lexicographicalPath(n, m, mappedMatrix);
}
}
 
// This code is contributed by pratham76


输出:
4
1 1
2 1
3 2
3 3

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。