给定一个由正整数组成的2d矩阵,任务是找到到达矩阵末端所需的最小步数。如果我们在单元格(i,j),则可以转到(i + X,j + Y)表示的所有单元格,使得X≥0 , Y≥0且X + Y = arr [i] [j] 。如果不存在路径,则打印-1 。
例子:
Input: arr[][] = {
{4, 1, 1},
{1, 1, 1},
{1, 1, 1}}
Output: 1
The path will be from {0, 0} -> {2, 2} as manhattan distance
between two is 4.
Thus, we are reaching there in 1 step.
Input: arr[][] = {
{1, 1, 2},
{1, 1, 1},
{2, 1, 1}}
Output: 3
一个简单的解决方案是探索所有可能需要花费指数时间的解决方案。
一个有效的解决方案是使用动态编程在多项式时间内解决此问题。让我们确定dp的状态。
假设我们在单元格(i,j)处。我们将尝试找到从该单元格到达单元格(n – 1,n – 1)所需的最小步骤数。
我们有arr [i] [j] + 1条可能的路径。
递归关系将是
dp[i][j] = 1 + min(dp[i][j + arr[i][j]], dp[i + 1][j + arr[i][j] – 1], …., dp[i + arr[i][j]][j])
为了减少递归关系中的项数,我们可以对X和Y的值设置上限。如何?
我们知道i + X
同样, Y
0 ≤ Y < N – j …(1)
X + Y = arr[i][j] …(2)
Substituting value of Y from second into first, we get
X ≥ arr[i][j] + j – N + 1
从上面我们得到了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) 。
我们的递归关系优化为
dp[i][j] = 1 + min(dp[i + max(0, arr[i][j] + j – N + 1)][j + arr[i][j] – max(0, arr[i][j] + j – N + 1)], …., dp[i + min(arr[i][j], N – i – 1)][j + arr[i][j] – 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)时间来解决。