📌  相关文章
📜  查找达到矩阵末尾所需的最低限度的步骤|套装2

📅  最后修改于: 2021-05-05 00:12:14             🧑  作者: Mango

给定一个由正整数组成的2d矩阵,任务是找到到达矩阵末端所需的最小步数。如果我们在单元格(i,j),则可以转到(i + X,j + Y)表示的所有单元格使得X≥0Y≥0X + Y = arr [i] [j] 。如果不存在路径,则打印-1

例子:

一个简单的解决方案是探索所有可能需要花费指数时间的解决方案。

一个有效的解决方案是使用动态编程在多项式时间内解决此问题。让我们确定dp的状态。
假设我们在单元格(i,j)处。我们将尝试找到从该单元格到达单元格(n – 1,n – 1)所需的最小步骤数。
我们有arr [i] [j] + 1条可能的路径。

递归关系将是

为了减少递归关系中的项数,我们可以对XY的值设置上限。如何?
我们知道i + X 。因此, X 否则它们将超出范围。
同样, Y

从上面我们得到了X约束的另一个下界,即X≥arr [i] [j] + j – N + 1
因此, X的新下界变为X≥max(0,arr [i] [j] + j – N + 1)
同样X≤min(arr [i] [j],N – i – 1)

我们的递归关系优化为

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
#define n 3
using namespace std;
  
// 2d array to store
// states of dp
int dp[n][n];
  
// Array to determine whether
// a state has been solved before
int v[n][n];
  
// Function to return the minimum steps required
int minSteps(int i, int j, int arr[][n])
{
  
    // Base cases
    if (i == n - 1 and j == n - 1)
        return 0;
  
    if (i > n - 1 || j > n - 1)
        return 9999999;
  
    // If a state has been solved before
    // it won't be evaluated again
    if (v[i][j])
        return dp[i][j];
  
    v[i][j] = 1;
    dp[i][j] = 9999999;
  
    // Recurrence relation
    for (int k = max(0, arr[i][j] + j - n + 1);
         k <= min(n - i - 1, arr[i][j]); k++) {
        dp[i][j] = min(dp[i][j], minSteps(i + k, j + arr[i][j] - k, arr));
    }
  
    dp[i][j]++;
  
    return dp[i][j];
}
  
// Driver code
int main()
{
    int arr[n][n] = { { 4, 1, 2 },
                      { 1, 1, 1 },
                      { 2, 1, 1 } };
  
    int ans = minSteps(0, 0, arr);
    if (ans >= 9999999)
        cout << -1;
    else
        cout << ans;
  
    return 0;
}


Java
// Java implementation of the approach
class GFG {
  
    static int n = 3;
  
    // 2d array to store
    // states of dp
    static int[][] dp = new int[n][n];
  
    // Array to determine whether
    // a state has been solved before
    static int[][] v = new int[n][n];
  
    // Function to return the minimum steps required
    static int minSteps(int i, int j, int arr[][])
    {
  
        // Base cases
        if (i == n - 1 && j == n - 1) {
            return 0;
        }
  
        if (i > n - 1 || j > n - 1) {
            return 9999999;
        }
  
        // If a state has been solved before
        // it won't be evaluated again
        if (v[i][j] == 1) {
            return dp[i][j];
        }
  
        v[i][j] = 1;
        dp[i][j] = 9999999;
  
        // Recurrence relation
        for (int k = Math.max(0, arr[i][j] + j - n + 1);
             k <= Math.min(n - i - 1, arr[i][j]); k++) {
            dp[i][j] = Math.min(dp[i][j],
                                minSteps(i + k, j + arr[i][j] - k, arr));
        }
  
        dp[i][j]++;
  
        return dp[i][j];
    }
  
    // Driver code
    public static void main(String[] args)
    {
        int arr[][] = { { 4, 1, 2 },
                        { 1, 1, 1 },
                        { 2, 1, 1 } };
  
        int ans = minSteps(0, 0, arr);
        if (ans >= 9999999) {
            System.out.println(-1);
        }
        else {
            System.out.println(ans);
        }
    }
}
  
// This code contributed by Rajput-Ji


Python3
# Python3 implementation of the approach 
  
import numpy as np 
n = 3
  
# 2d array to store 
# states of dp 
dp = np.zeros((n,n))
  
# Array to determine whether 
# a state has been solved before 
v = np.zeros((n,n)); 
  
# Function to return the minimum steps required 
def minSteps(i, j, arr) : 
  
    # Base cases 
    if (i == n - 1 and j == n - 1) :
        return 0; 
  
    if (i > n - 1 or j > n - 1) :
        return 9999999; 
  
    # If a state has been solved before 
    # it won't be evaluated again 
    if (v[i][j]) :
        return dp[i][j]; 
  
    v[i][j] = 1; 
    dp[i][j] = 9999999; 
  
    # Recurrence relation 
    for k in range(max(0, arr[i][j] + j - n + 1),min(n - i - 1, arr[i][j]) + 1) :
        dp[i][j] = min(dp[i][j], minSteps(i + k, j + arr[i][j] - k, arr)); 
      
  
    dp[i][j] += 1; 
  
    return dp[i][j]; 
  
  
# Driver code 
if __name__ == "__main__" : 
  
    arr = [ 
            [ 4, 1, 2 ], 
            [ 1, 1, 1 ], 
            [ 2, 1, 1 ] 
            ]; 
  
    ans = minSteps(0, 0, arr); 
    if (ans >= 9999999) :
        print(-1); 
    else :
        print(ans); 
  
# This code is contributed by AnkitRai01


C#
// C# implementation of the approach
using System;
  
class GFG
{
    static int n = 3;
  
    // 2d array to store
    // states of dp
    static int[,] dp = new int[n, n];
  
    // Array to determine whether
    // a state has been solved before
    static int[,] v = new int[n, n];
  
    // Function to return the minimum steps required
    static int minSteps(int i, int j, int [,]arr)
    {
  
        // Base cases
        if (i == n - 1 && j == n - 1)
        {
            return 0;
        }
  
        if (i > n - 1 || j > n - 1) 
        {
            return 9999999;
        }
  
        // If a state has been solved before
        // it won't be evaluated again
        if (v[i, j] == 1) 
        {
            return dp[i, j];
        }
  
        v[i, j] = 1;
        dp[i, j] = 9999999;
  
        // Recurrence relation
        for (int k = Math.Max(0, arr[i,j] + j - n + 1);
            k <= Math.Min(n - i - 1, arr[i,j]); k++)
        {
            dp[i,j] = Math.Min(dp[i,j],
                                minSteps(i + k, j + arr[i,j] - k, arr));
        }
  
        dp[i,j]++;
  
        return dp[i,j];
    }
  
    // Driver code
    static public void Main ()
    {
        int [,]arr = { { 4, 1, 2 },
                        { 1, 1, 1 },
                        { 2, 1, 1 } };
  
        int ans = minSteps(0, 0, arr);
        if (ans >= 9999999) 
        {
            Console.WriteLine(-1);
        }
        else 
        {
            Console.WriteLine(ans);
        }
    }
}
  
// This code contributed by ajit.


输出:
1

上述方法的时间复杂度将为O(n 3 )。每个状态在最坏的情况下需要O(n)时间来解决。