📜  查找最大长度的蛇序列

📅  最后修改于: 2021-04-27 23:59:18             🧑  作者: Mango

给定一个数字网格,找到最大长度的Snake序列并打印出来。如果存在多个最大长度的蛇形序列,请打印其中的任何一个。

蛇形序列由网格中的相邻数字组成,因此对于每个数字,右侧的数字或其下方的数字为其值的+1或-1。例如,如果您位于网格中的位置(x,y),则可以向右移动,即(x,y + 1)(如果该数字为±1),也可以向下移动,即(x + 1,y),如果该数字是±1。

例如,

9,6,5,2
8、7、6、5
7,3,1,6
1,1,1,7

在上面的网格中,最长的蛇序列为:(9、8、7、6、5、6、7)

下图显示了所有可能的路径–

蛇序列

强烈建议您最小化浏览器,然后自己尝试。

这个想法是使用动态编程。对于矩阵的每个单元,我们保留一条在当前单元中结束的蛇的最大长度。最大长度的蛇序列将具有最大值。最大值单元格将对应于蛇的尾巴。为了打印蛇,我们需要从尾巴一直回溯到蛇的头部。

T [i] [i]代表一条蛇的最大长度,该蛇在单元格(i,j)处结束,那么对于给定的矩阵M,DP关系定义为:

T [0] [0] = 0
如果M [i] [j] = M [i] [j – 1]±1,则T [i] [j] = max(T [i] [j],T [i] [j – 1] + 1)
如果M [i] [j] = M [i – 1] [j]±1,则T [i] [j] = max(T [i] [j],T [i – 1] [j] + 1)

以下是该想法的实现–

C++
// C++ program to find maximum length
// Snake sequence and print it
#include 
using namespace std;
#define M 4
#define N 4
  
struct Point
{
    int x, y;
};
  
// Function to find maximum length Snake sequence path
// (i, j) corresponds to tail of the snake
list findPath(int grid[M][N], int mat[M][N],
                     int i, int j)
{
    list path;
  
    Point pt = {i, j};
    path.push_front(pt);
  
    while (grid[i][j] != 0)
    {
       if (i > 0 &&
           grid[i][j] - 1 == grid[i - 1][j])
       {
           pt = {i - 1, j};
           path.push_front(pt);
           i--;
       }
       else if (j > 0 &&
                grid[i][j] - 1 == grid[i][j - 1])
       {
           pt = {i, j - 1};
           path.push_front(pt);
           j--;
       }
    }
  
    return path;
}
  
// Function to find maximum length Snake sequence
void findSnakeSequence(int mat[M][N])
{
    // table to store results of subproblems
    int lookup[M][N];
  
    // initialize by 0
    memset(lookup, 0, sizeof lookup);
  
    // stores maximum length of Snake sequence
    int max_len = 0;
  
    // store cordinates to snake's tail
    int max_row = 0;
    int max_col = 0;
  
    // fill the table in bottom-up fashion
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            // do except for (0, 0) cell
            if (i || j)
            {
                // look above
                if (i > 0 &&
                    abs(mat[i - 1][j] - mat[i][j]) == 1)
                {
                    lookup[i][j] = max(lookup[i][j],
                               lookup[i - 1][j] + 1);
  
                    if (max_len < lookup[i][j])
                    {
                        max_len = lookup[i][j];
                        max_row = i, max_col = j;
                    }
                }
  
                // look left
                if (j > 0 &&
                    abs(mat[i][j - 1] - mat[i][j]) == 1)
                {
                    lookup[i][j] = max(lookup[i][j],
                                       lookup[i][j - 1] + 1);
                    if (max_len < lookup[i][j])
                    {
                        max_len = lookup[i][j];
                        max_row = i, max_col = j;
                    }
                }
            }
        }
    }
  
    cout << "Maximum length of Snake sequence is: "
         << max_len << endl;
  
    // find maximum length Snake sequence path
    list path = findPath(lookup, mat, max_row,
                                             max_col);
  
    cout << "Snake sequence is:";
    for (auto it = path.begin(); it != path.end(); it++)
        cout << endl << mat[it->x][it->y] << " ("
             << it->x << ", " << it->y << ")" ;
}
  
// Driver code
int main()
{
    int mat[M][N] =
    {
        {9, 6, 5, 2},
        {8, 7, 6, 5},
        {7, 3, 1, 6},
        {1, 1, 1, 7},
    };
  
    findSnakeSequence(mat);
  
    return 0;
}


Java
// Java program to find maximum length
// Snake sequence and print it
import java.util.*;
  
class GFG 
{
  
static int M = 4;
static int N = 4;
  
static class Point
{
    int x, y;
  
    public Point(int x, int y) 
    {
        this.x = x;
        this.y = y;
    }
};
  
// Function to find maximum length Snake sequence path
// (i, j) corresponds to tail of the snake
static List findPath(int grid[][],   
                            int mat[][], 
                            int i, int j)
{
    List path = new LinkedList<>();
  
    Point pt = new Point(i, j);
    path.add(0, pt);
  
    while (grid[i][j] != 0)
    {
        if (i > 0 &&
            grid[i][j] - 1 == grid[i - 1][j])
        {
            pt = new Point(i - 1, j);
            path.add(0, pt);
            i--;
        }
        else if (j > 0 && grid[i][j] - 1 == 
                          grid[i][j - 1])
        {
            pt = new Point(i, j - 1);
            path.add(0, pt);
            j--;
        }
    }
    return path;
}
  
// Function to find maximum length Snake sequence
static void findSnakeSequence(int mat[][])
{
    // table to store results of subproblems
    int [][]lookup = new int[M][N];
  
    // initialize by 0
  
    // stores maximum length of Snake sequence
    int max_len = 0;
  
    // store cordinates to snake's tail
    int max_row = 0;
    int max_col = 0;
  
    // fill the table in bottom-up fashion
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            // do except for (0, 0) cell
            if (i != 0 || j != 0)
            {
                // look above
                if (i > 0 &&
                    Math.abs(mat[i - 1][j] - 
                             mat[i][j]) == 1)
                {
                    lookup[i][j] = Math.max(lookup[i][j],
                                            lookup[i - 1][j] + 1);
  
                    if (max_len < lookup[i][j])
                    {
                        max_len = lookup[i][j];
                        max_row = i; max_col = j;
                    }
                }
  
                // look left
                if (j > 0 &&
                    Math.abs(mat[i][j - 1] - 
                             mat[i][j]) == 1)
                {
                    lookup[i][j] = Math.max(lookup[i][j],
                                            lookup[i][j - 1] + 1);
                    if (max_len < lookup[i][j])
                    {
                        max_len = lookup[i][j];
                        max_row = i; max_col = j;
                    }
                }
            }
        }
    }
    System.out.print("Maximum length of Snake " + 
                     "sequence is: " + max_len + "\n");
  
    // find maximum length Snake sequence path
    List path = findPath(lookup, mat, max_row,
                                             max_col);
  
    System.out.print("Snake sequence is:");
    for (Point it : path)
        System.out.print("\n" + mat[it.x][it.y] + " (" + 
                                    it.x + ", " + it.y + ")");
}
  
// Driver code
public static void main(String[] args)
{
    int mat[][] = {{9, 6, 5, 2},
                   {8, 7, 6, 5},
                   {7, 3, 1, 6},
                   {1, 1, 1, 7}};
  
    findSnakeSequence(mat);
}
}
  
// This code is contributed by 29AjayKumar


Python3
# Python program to find maximum length
# Snake sequence and print it
  
M = 4
N = 4
  
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
  
# Function to find maximum length Snake sequence path
# (i, j) corresponds to tail of the snake
def findPath(grid, mat, i, j):
    path = list()
  
    pt = Point(i, j)
    path.append(pt)
  
    while (grid[i][j] != 0):
        if (i > 0 and grid[i][j]-1 == grid[i-1][j]):
            pt = Point(i-1, j)
            path.append(pt)
            i -= 1
        elif (j > 0 and grid[i][j]-1 == grid[i][j-1]):
            pt = Point(i, j-1)
            path.append(pt)
            j -= 1
    return path
  
# Function to find maximum length Snake sequence
def findSnakeSequence(mat):
  
    # table to store results of subproblems
    # initialize by 0
    lookup = [[0 for i in range(N)] for j in range(M)]
  
    # stores maximum length of Snake sequence
    max_len = 0
  
    # store cordinates to snake's tail
    max_row = 0
    max_col = 0
  
    # fill the table in bottom-up fashion
    for i in range(M):
        for j in range(N):
            # do except for (0, 0) cell
            if (i or j):
                # look above
                if (i > 0 and
                    abs(mat[i-1][j] - mat[i][j]) == 1):
                    lookup[i][j] = max(lookup[i][j],
                                       lookup[i-1][j] + 1)
                    if (max_len < lookup[i][j]):
                        max_len = lookup[i][j]
                        max_row = i
                        max_col = j
  
                # look left
                if (j > 0 and
                    abs(mat[i][j-1] - mat[i][j]) == 1):
                    lookup[i][j] = max(lookup[i][j],
                                       lookup[i][j-1] + 1)
                    if (max_len < lookup[i][j]):
                        max_len = lookup[i][j]
                        max_row = i
                        max_col = j
  
    print("Maximum length of Snake sequence is:", max_len)
  
    # find maximum length Snake sequence path
    path = findPath(lookup, mat, max_row, max_col)
  
    print("Snake sequence is:")
    for ele in reversed(path):
        print(mat[ele.x][ele.y],
              " (", ele.x, ", ", ele.y, ")", sep = "")
  
# Driver code
mat = [[9, 6, 5, 2],
       [8, 7, 6, 5],
       [7, 3, 1, 6],
       [1, 1, 1, 7]]
  
findSnakeSequence(mat)
  
# This code is contributed
# by Soumen Ghosh


C#
// C# program to find maximum length
// Snake sequence and print it
using System;
using System.Collections.Generic;
      
class GFG 
{
static int M = 4;
static int N = 4;
  
public class Point
{
    public int x, y;
  
    public Point(int x, int y) 
    {
        this.x = x;
        this.y = y;
    }
};
  
// Function to find maximum length Snake sequence path
// (i, j) corresponds to tail of the snake
static List findPath(int [,]grid, 
                            int [,]mat, 
                            int i, int j)
{
    List path = new List();
  
    Point pt = new Point(i, j);
    path.Insert(0, pt);
  
    while (grid[i, j] != 0)
    {
        if (i > 0 &&
            grid[i, j] - 1 == grid[i - 1, j])
        {
            pt = new Point(i - 1, j);
            path.Insert(0, pt);
            i--;
        }
        else if (j > 0 && grid[i, j] - 1 == 
                          grid[i, j - 1])
        {
            pt = new Point(i, j - 1);
            path.Insert(0, pt);
            j--;
        }
    }
    return path;
}
  
// Function to find maximum length Snake sequence
static void findSnakeSequence(int [,]mat)
{
    // table to store results of subproblems
    int [,]lookup = new int[M, N];
  
    // initialize by 0
  
    // stores maximum length of Snake sequence
    int max_len = 0;
  
    // store cordinates to snake's tail
    int max_row = 0;
    int max_col = 0;
  
    // fill the table in bottom-up fashion
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            // do except for (0, 0) cell
            if (i != 0 || j != 0)
            {
                // look above
                if (i > 0 &&
                    Math.Abs(mat[i - 1, j] - 
                             mat[i, j]) == 1)
                {
                    lookup[i, j] = Math.Max(lookup[i, j],
                                            lookup[i - 1, j] + 1);
  
                    if (max_len < lookup[i,j])
                    {
                        max_len = lookup[i, j];
                        max_row = i; max_col = j;
                    }
                }
  
                // look left
                if (j > 0 &&
                    Math.Abs(mat[i, j - 1] - 
                             mat[i, j]) == 1)
                {
                    lookup[i, j] = Math.Max(lookup[i, j],
                                            lookup[i, j - 1] + 1);
                    if (max_len < lookup[i, j])
                    {
                        max_len = lookup[i, j];
                        max_row = i; max_col = j;
                    }
                }
            }
        }
    }
    Console.Write("Maximum length of Snake " + 
                  "sequence is: " + max_len + "\n");
  
    // find maximum length Snake sequence path
    List path = findPath(lookup, mat, max_row,
                                             max_col);
  
    Console.Write("Snake sequence is:");
    foreach (Point it in path)
        Console.Write("\n" + mat[it.x,it.y] + 
                      " (" + it.x + ", " + it.y + ")");
}
  
// Driver code
public static void Main(String[] args)
{
    int [,]mat = {{9, 6, 5, 2},
                  {8, 7, 6, 5},
                  {7, 3, 1, 6},
                  {1, 1, 1, 7}};
  
    findSnakeSequence(mat);
}
}
  
// This code is contributed by Princi Singh


输出 :

Maximum length of Snake sequence is: 6
Snake sequence is:
9 (0, 0)
8 (1, 0)
7 (1, 1)
6 (1, 2)
5 (1, 3)
6 (2, 3)
7 (3, 3)

上述解决方案的时间复杂度为O(M * N)。上述解决方案使用的辅助空间为O(M * N)。如果不需要打印蛇,则可以将空间进一步减小为O(N),因为我们仅使用最后一行的结果。

参考:堆栈溢出