在给定约束的矩阵中求最长路径

给定一个n*n矩阵,其中所有数字都是不同的,求出最大长度路径(从任何单元格开始),这样路径上的所有单元格都以1为差的递增顺序排列。 我们可以从一个给定的单元(i,j)向4个方向移动,也就是说,我们可以在相邻单元的差值为1的情况下移动到(i+1,j)或(i,j+1)或(i-1,j)或(i,j-1)。 例子:

null
Input:  mat[][] = {{1, 2, 9}                   {5, 3, 8}                   {4, 6, 7}}Output: 4The longest path is 6-7-8-9. 

这个想法很简单,我们计算从每个细胞开始的最长路径。一旦我们计算了所有单元的最长路径,我们将返回所有最长路径的最大值。这种方法的一个重要观察结果是许多重叠的子问题。因此,这个问题可以用动态规划来优化解决。 下面是基于动态编程的实现,它使用一个查找表dp[][]来检查问题是否已经解决。

C++

// C++ program to find the longest path in a matrix
// with given constraints
#include <bits/stdc++.h>
#define n 3
using namespace std;
// Returns length of the longest path beginning with mat[i][j].
// This function mainly uses lookup table dp[n][n]
int findLongestFromACell( int i, int j, int mat[n][n], int dp[n][n])
{
if (i < 0 || i >= n || j < 0 || j >= n)
return 0;
// If this subproblem is already solved
if (dp[i][j] != -1)
return dp[i][j];
// To store the path lengths in all the four directions
int x = INT_MIN, y = INT_MIN, z = INT_MIN, w = INT_MIN;
// Since all numbers are unique and in range from 1 to n*n,
// there is atmost one possible direction from any cell
if (j < n - 1 && ((mat[i][j] + 1) == mat[i][j + 1]))
x = 1 + findLongestFromACell(i, j + 1, mat, dp);
if (j > 0 && (mat[i][j] + 1 == mat[i][j - 1]))
y = 1 + findLongestFromACell(i, j - 1, mat, dp);
if (i > 0 && (mat[i][j] + 1 == mat[i - 1][j]))
z = 1 + findLongestFromACell(i - 1, j, mat, dp);
if (i < n - 1 && (mat[i][j] + 1 == mat[i + 1][j]))
w = 1 + findLongestFromACell(i + 1, j, mat, dp);
// If none of the adjacent fours is one greater we will take 1
// otherwise we will pick maximum from all the four directions
return dp[i][j] = max(x, max(y, max(z, max(w, 1))));
}
// Returns length of the longest path beginning with any cell
int finLongestOverAll( int mat[n][n])
{
int result = 1; // Initialize result
// Create a lookup table and fill all entries in it as -1
int dp[n][n];
memset (dp, -1, sizeof dp);
// Compute longest path beginning from all cells
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < n; j++) {
if (dp[i][j] == -1)
findLongestFromACell(i, j, mat, dp);
// Update result if needed
result = max(result, dp[i][j]);
}
}
return result;
}
// Driver program
int main()
{
int mat[n][n] = { { 1, 2, 9 },
{ 5, 3, 8 },
{ 4, 6, 7 } };
cout << "Length of the longest path is "
<< finLongestOverAll(mat);
return 0;
}


JAVA

// Java program to find the longest path in a matrix
// with given constraints
class GFG {
public static int n = 3 ;
// Function that returns length of the longest path
// beginning with mat[i][j]
// This function mainly uses lookup table dp[n][n]
static int findLongestFromACell( int i, int j, int mat[][], int dp[][])
{
// Base case
if (i < 0 || i >= n || j < 0 || j >= n)
return 0 ;
// If this subproblem is already solved
if (dp[i][j] != - 1 )
return dp[i][j];
// To store the path lengths in all the four directions
int x = Integer.MIN_VALUE, y = Integer.MIN_VALUE, z = Integer.MIN_VALUE, w = Integer.MIN_VALUE;
// Since all numbers are unique and in range from 1 to n*n,
// there is atmost one possible direction from any cell
if (j < n - 1 && ((mat[i][j] + 1 ) == mat[i][j + 1 ]))
x = dp[i][j] = 1 + findLongestFromACell(i, j + 1 , mat, dp);
if (j > 0 && (mat[i][j] + 1 == mat[i][j - 1 ]))
y = dp[i][j] = 1 + findLongestFromACell(i, j - 1 , mat, dp);
if (i > 0 && (mat[i][j] + 1 == mat[i - 1 ][j]))
z = dp[i][j] = 1 + findLongestFromACell(i - 1 , j, mat, dp);
if (i < n - 1 && (mat[i][j] + 1 == mat[i + 1 ][j]))
w = dp[i][j] = 1 + findLongestFromACell(i + 1 , j, mat, dp);
// If none of the adjacent fours is one greater we will take 1
// otherwise we will pick maximum from all the four directions
return dp[i][j] = Math.max(x, Math.max(y, Math.max(z, Math.max(w, 1 ))));
}
// Function that returns length of the longest path
// beginning with any cell
static int finLongestOverAll( int mat[][])
{
// Initialize result
int result = 1 ;
// Create a lookup table and fill all entries in it as -1
int [][] dp = new int [n][n];
for ( int i = 0 ; i < n; i++)
for ( int j = 0 ; j < n; j++)
dp[i][j] = - 1 ;
// Compute longest path beginning from all cells
for ( int i = 0 ; i < n; i++) {
for ( int j = 0 ; j < n; j++) {
if (dp[i][j] == - 1 )
findLongestFromACell(i, j, mat, dp);
// Update result if needed
result = Math.max(result, dp[i][j]);
}
}
return result;
}
// driver program
public static void main(String[] args)
{
int mat[][] = { { 1 , 2 , 9 },
{ 5 , 3 , 8 },
{ 4 , 6 , 7 } };
System.out.println( "Length of the longest path is " + finLongestOverAll(mat));
}
}
// Contributed by Pramod Kumar


Python3

# Python3 program to find the longest path in a matrix
# with given constraints
n = 3
# Returns length of the longest path beginning with mat[i][j].
# This function mainly uses lookup table dp[n][n]
def findLongestFromACell(i, j, mat, dp):
# Base case
if (i< 0 or i> = n or j< 0 or j> = n):
return 0
# If this subproblem is already solved
if (dp[i][j] ! = - 1 ):
return dp[i][j]
# To store the path lengths in all the four directions
x, y, z, w = - 1 , - 1 , - 1 , - 1
# Since all numbers are unique and in range from 1 to n * n,
# there is atmost one possible direction from any cell
if (j<n - 1 and ((mat[i][j] + 1 ) = = mat[i][j + 1 ])):
x = 1 + findLongestFromACell(i, j + 1 , mat, dp)
if (j> 0 and (mat[i][j] + 1 = = mat[i][j - 1 ])):
y = 1 + findLongestFromACell(i, j - 1 , mat, dp)
if (i> 0 and (mat[i][j] + 1 = = mat[i - 1 ][j])):
z = 1 + findLongestFromACell(i - 1 , j, mat, dp)
if (i<n - 1 and (mat[i][j] + 1 = = mat[i + 1 ][j])):
w = 1 + findLongestFromACell(i + 1 , j, mat, dp)
# If none of the adjacent fours is one greater we will take 1
# otherwise we will pick maximum from all the four directions
dp[i][j] = max (x, max (y, max (z, max (w, 1 ))))
return dp[i][j]
# Returns length of the longest path beginning with any cell
def finLongestOverAll(mat):
result = 1 # Initialize result
# Create a lookup table and fill all entries in it as -1
dp = [[ - 1 for i in range (n)] for i in range (n)]
# Compute longest path beginning from all cells
for i in range (n):
for j in range (n):
if (dp[i][j] = = - 1 ):
findLongestFromACell(i, j, mat, dp)
# Update result if needed
result = max (result, dp[i][j]);
return result
# Driver program
mat = [[ 1 , 2 , 9 ],
[ 5 , 3 , 8 ],
[ 4 , 6 , 7 ]]
print ( "Length of the longest path is " , finLongestOverAll(mat))
# this code is improved by sahilshelangia


Javascript

<script>
// JavaScript program to find the longest path in a matrix
// with given constraints
let n = 3;
// Returns length of the longest path beginning with mat[i][j].
// This function mainly uses lookup table dp[n][n]
function findLongestFromACell( i, j, mat, dp){
if (i < 0 || i >= n || j < 0 || j >= n)
return 0;
// If this subproblem is already solved
if (dp[i][j] != -1)
return dp[i][j];
// To store the path lengths in all the four directions
let x,y,z,w;
x = -1;
y = -1;
z = -1
w = -1;
// Since all numbers are unique and in range from 1 to n*n,
// there is atmost one possible direction from any cell
if (j < n - 1 && ((mat[i][j] + 1) == mat[i][j + 1]))
x = 1 + findLongestFromACell(i, j + 1, mat, dp);
if (j > 0 && (mat[i][j] + 1 == mat[i][j - 1]))
y = 1 + findLongestFromACell(i, j - 1, mat, dp);
if (i > 0 && (mat[i][j] + 1 == mat[i - 1][j]))
z = 1 + findLongestFromACell(i - 1, j, mat, dp);
if (i < n - 1 && (mat[i][j] + 1 == mat[i + 1][j]))
w = 1 + findLongestFromACell(i + 1, j, mat, dp);
// If none of the adjacent fours is one greater we will take 1
// otherwise we will pick maximum from all the four directions
dp[i][j] = Math.max(x, Math.max(y, Math.max(z, Math.max(w, 1))));
return dp[i][j];
}
// Returns length of the longest path beginning with any cell
function finLongestOverAll( mat){
let result = 1; // Initialize result
// Create a lookup table and fill all entries in it as -1
var dp = [];
for ( var y = 0; y < n; y++ ) {
dp[ y ] = [];
for ( var x = 0; x < n; x++ ) {
dp[ y ][ x ] = -1;
}
}
// Compute longest path beginning from all cells
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (dp[i][j] == -1)
findLongestFromACell(i, j, mat, dp);
// Update result if needed
result = Math.max(result, dp[i][j]);
}
}
return result;
}
// Driver program
let mat = [[ 1, 2, 9 ],
[ 5, 3, 8 ],
[ 4, 6, 7 ]];
document.write( "Length of the longest path is " );
document.write( finLongestOverAll(mat));
</script>


C#

// C# program to find the longest path
// in a matrix with given constraints
using System;
class GFG {
public static int n = 3;
// Function that returns length of
// the longest path beginning with mat[i][j]
// This function mainly uses lookup
// table dp[n][n]
public static int findLongestFromACell( int i, int j,
int [][] mat,
int [][] dp)
{
// Base case
if (i < 0 || i >= n || j < 0 || j >= n) {
return 0;
}
// If this subproblem is
// already solved
if (dp[i][j] != -1) {
return dp[i][j];
}
// To store the path lengths in all the four directions
int x = int .MinValue, y = int .MinValue, z = int .MinValue, w = int .MinValue;
// Since all numbers are unique and
// in range from 1 to n*n, there is
// atmost one possible direction
// from any cell
if (j < n - 1 && ((mat[i][j] + 1) == mat[i][j + 1])) {
x = dp[i][j] = 1 + findLongestFromACell(i, j + 1, mat, dp);
}
if (j > 0 && (mat[i][j] + 1 == mat[i][j - 1])) {
y = dp[i][j] = 1 + findLongestFromACell(i, j - 1, mat, dp);
}
if (i > 0 && (mat[i][j] + 1 == mat[i - 1][j])) {
z = dp[i][j] = 1 + findLongestFromACell(i - 1, j, mat, dp);
}
if (i < n - 1 && (mat[i][j] + 1 == mat[i + 1][j])) {
w = dp[i][j] = 1 + findLongestFromACell(i + 1, j, mat, dp);
}
// If none of the adjacent fours is one greater we will take 1
// otherwise we will pick maximum from all the four directions
dp[i][j] = Math.Max(x, Math.Max(y, Math.Max(z, Math.Max(w, 1))));
return dp[i][j];
}
// Function that returns length of the
// longest path beginning with any cell
public static int finLongestOverAll( int [][] mat)
{
// Initialize result
int result = 1;
// Create a lookup table and fill
// all entries in it as -1
int [][] dp = RectangularArrays.ReturnRectangularIntArray(n, n);
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < n; j++) {
dp[i][j] = -1;
}
}
// Compute longest path beginning
// from all cells
for ( int i = 0; i < n; i++) {
for ( int j = 0; j < n; j++) {
if (dp[i][j] == -1) {
findLongestFromACell(i, j, mat, dp);
}
// Update result if needed
result = Math.Max(result, dp[i][j]);
}
}
return result;
}
public static class RectangularArrays {
public static int [][] ReturnRectangularIntArray( int size1,
int size2)
{
int [][] newArray = new int [size1][];
for ( int array1 = 0;
array1 < size1; array1++) {
newArray[array1] = new int [size2];
}
return newArray;
}
}
// Driver Code
public static void Main( string [] args)
{
int [][] mat = new int [][] {
new int [] { 1, 2, 9 },
new int [] { 5, 3, 8 },
new int [] { 4, 6, 7 }
};
Console.WriteLine( "Length of the longest path is " + finLongestOverAll(mat));
}
}
// This code is contributed by Shrikant13


输出:

Length of the longest path is 4

上述解的时间复杂度为O(n) 2. ).乍一看可能更像。如果我们仔细观察,我们可以注意到dp[i][j]的所有值只计算一次。 本文由 埃克塔·戈尔 。如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请发表评论

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享