📜  矩阵中最大的之字形序列

📅  最后修改于: 2021-05-04 08:03:39             🧑  作者: Mango

给定大小为nxn的矩阵,找到总和最大的之字形序列的总和。之字形序列从顶部开始,在底部结束。序列的两个连续元素不能属于同一列。
例子:

Input : mat[][] = 3  1  2
                  4  8  5
                  6  9  7
Output : 18
Zigzag sequence is: 3->8->7
Another such sequence is 2->4->7

Input : mat[][] =  4  2  1
                   3  9  6
                  11  3 15
Output : 28

这个问题具有最优子结构

Maximum Zigzag sum starting from arr[i][j] to a 
bottom cell can be written as :
zzs(i, j) = arr[i][j] + max(zzs(i+1, k)), 
               where k = 0, 1, 2 and k != j
zzs(i, j) = arr[i][j], if i = n-1 

We have to find the largest among all as
Result = zzs(0, j) where 0 <= j < n
C++
// C++ program to find the largest sum zigzag sequence
#include 
using namespace std;
  
const int MAX = 100;
  
// Returns largest sum of a Zigzag sequence starting
// from (i, j) and ending at a bottom cell.
int largestZigZagSumRec(int mat[][MAX], int i,
                                int j, int n)
{
   // If we have reached bottom
   if (i == n-1)
     return mat[i][j];
  
   // Find the largest sum by considering all
   // possible next elements in sequence.
   int zzs = 0;
   for (int k=0; k


Java
// Java program to find the largest sum 
// zigzag sequence
import java.io.*;
  
class GFG {
  
    static int MAX = 100;
      
    // Returns largest sum of a Zigzag 
    // sequence starting from (i, j) 
    // and ending at a bottom cell.
    static int largestZigZagSumRec(int mat[][],
                            int i, int j, int n)
    {
          
        // If we have reached bottom
        if (i == n-1)
            return mat[i][j];
          
        // Find the largest sum by considering all
        // possible next elements in sequence.
        int zzs = 0;
          
        for (int k=0; k


Python 3
# Python3 program to find the largest
# sum zigzag sequence
MAX = 100
  
# Returns largest sum of a Zigzag 
# sequence starting from (i, j) and
# ending at a bottom cell.
def largestZigZagSumRec( mat, i, j, n):
      
    # If we have reached bottom
    if (i == n-1):
        return mat[i][j]
      
    # Find the largest sum by considering all
    # possible next elements in sequence.
    zzs = 0
    for k in range(n):
        if (k != j):
            zzs = max(zzs, largestZigZagSumRec(mat, i + 1, k, n))
      
    return zzs + mat[i][j]
  
# Returns largest possible sum of a 
# Zizag sequence starting from top 
# and ending at bottom.
def largestZigZag(mat, n):
          
    # Consider all cells of top row as
    # starting point
    res = 0
    for j in range(n):
        res = max(res, largestZigZagSumRec(mat, 0, j, n))
      
    return res
  
# Driver Code
if __name__ == "__main__":
    n = 3
    mat = [ [4, 2, 1],
            [3, 9, 6],
            [11, 3, 15]]
    print("Largest zigzag sum: " , 
           largestZigZag(mat, n))
  
# This code is contributed by ChitraNayal


C#
// C# program to find the largest sum 
// zigzag sequence
using System;
class GFG {
  
    // static int MAX = 100;
      
    // Returns largest sum of a Zigzag 
    // sequence starting from (i, j) 
    // and ending at a bottom cell.
    static int largestZigZagSumRec(int [,]mat,
                          int i, int j, int n)
    {
          
        // If we have reached bottom
        if (i == n-1)
            return mat[i,j];
          
        // Find the largest sum by considering all
        // possible next elements in sequence.
        int zzs = 0;
          
        for (int k = 0; k < n; k++)
            if (k != j)
            zzs = Math.Max(zzs, largestZigZagSumRec(mat, 
                                           i + 1, k, n));
          
        return zzs + mat[i,j];
    }
      
    // Returns largest possible
    // sum of a Zizag sequence 
    // starting from top and ending 
    // at bottom.
    static int largestZigZag(int [,]mat, int n)
    {
          
        // Consider all cells of 
        // top row as starting
        // point
        int res = 0;
        for (int j = 0; j < n; j++)
            res = Math.Max(res, 
                largestZigZagSumRec(mat, 0, j, n));
          
        return res;
    }
      
    // Driver Code
    public static void Main ()
    {
        int n = 3;
        int [,]mat = {{4, 2, 1},
                      {3, 9, 6},
                      {11, 3, 15}};
        Console.WriteLine("Largest zigzag sum: "
                           + largestZigZag(mat, n));
    }
}
  
// This code is contributed by anuj_67.


PHP


C++
// Memoization based C++ program to find the largest
// sum zigzag sequence
#include 
using namespace std;
  
const int MAX = 100;
int dp[MAX][MAX];
  
// Returns largest sum of a Zigzag sequence starting
// from (i, j) and ending at a bottom cell.
int largestZigZagSumRec(int mat[][MAX], int i,
                                int j, int n)
{
   if (dp[i][j] != -1)
      return dp[i][j];
  
   // If we have reached bottom
   if (i == n-1)
     return (dp[i][j] = mat[i][j]);
  
   // Find the largest sum by considering all
   // possible next elements in sequence.
   int zzs = 0;
   for (int k=0; k


Java
// Memoization based Java program to find the largest
// sum zigzag sequence
class GFG
{
  
static int MAX = 100;
static int [][]dp = new int[MAX][MAX];
  
// Returns largest sum of a Zigzag sequence starting
// from (i, j) and ending at a bottom cell.
static int largestZigZagSumRec(int mat[][], int i,
                                int j, int n)
{
    if (dp[i][j] != -1)
        return dp[i][j];
      
    // If we have reached bottom
    if (i == n - 1)
        return (dp[i][j] = mat[i][j]);
      
    // Find the largest sum by considering all
    // possible next elements in sequence.
    int zzs = 0;
    for (int k = 0; k < n; k++)
        if (k != j)
            zzs = Math.max(zzs, largestZigZagSumRec(mat,
                                    i + 1, k, n));
      
    return (dp[i][j] = (zzs + mat[i][j]));
}
  
// Returns largest possible sum of a Zizag sequence
// starting from top and ending at bottom.
static int largestZigZag(int mat[][], int n)
{
    for (int i = 0; i < MAX; i++)
        for (int k = 0; k < MAX; k++)
                dp[i][k] = -1;
      
    // Consider all cells of top row as starting point
    int res = 0;
    for (int j = 0; j < n; j++)
        res = Math.max(res, largestZigZagSumRec(mat,
                                           0, j, n));
      
    return res;
}
  
// Driver code
public static void main(String[] args)
{
    int n = 3;
    int mat[][] = { {4, 2, 1},
                    {3, 9, 6},
                    {11, 3, 15}};
    System.out.print("Largest zigzag sum: " + 
                        largestZigZag(mat, n));
}
}
  
// This code is contributed by PrinciRaj1992


Python3
# Memoization based Python3 program to find the largest
# sum zigzag sequence
MAX = 100;
  
dp = [[0 for i in range(MAX)] for j in range(MAX)]
  
# Returns largest sum of a Zigzag sequence starting
# from (i, j) and ending at a bottom cell.
def largestZigZagSumRec(mat, i, j, n):
    if (dp[i][j] != -1):
        return dp[i][j];
  
    # If we have reached bottom
    if (i == n - 1):
        dp[i][j] = mat[i][j];
        return (dp[i][j]);
  
    # Find the largest sum by considering all
    # possible next elements in sequence.
    zzs = 0;
    for k in range(n):
        if (k != j):
            zzs = max(zzs, largestZigZagSumRec(mat,
                     i + 1, k, n));
    dp[i][j] = (zzs + mat[i][j]);
    return (dp[i][j]);
  
# Returns largest possible sum of a Zizag sequence
# starting from top and ending at bottom.
def largestZigZag(mat, n):
    for i in range(MAX):
        for k in range(MAX):
            dp[i][k] = -1;
  
    # Consider all cells of top row as starting point
    res = 0;
    for j in range(n):
        res = max(res, largestZigZagSumRec(mat, 0, j, n));
  
    return res;
  
# Driver code
if __name__ == '__main__':
    n = 3;
    mat = [[4, 2, 1], [3, 9, 6], [11, 3, 15]];
    print("Largest zigzag sum: ", largestZigZag(mat, n));
  
# This code is contributed by Rajput-Ji


C#
// Memoization based C# program to find the largest
// sum zigzag sequence
using System;
  
class GFG
{
  
static int MAX = 100;
static int [,]dp = new int[MAX, MAX];
  
// Returns largest sum of a Zigzag sequence starting
// from (i, j) and ending at a bottom cell.
static int largestZigZagSumRec(int [,]mat, int i,
                                int j, int n)
{
    if (dp[i, j] != -1)
        return dp[i, j];
      
    // If we have reached bottom
    if (i == n - 1)
        return (dp[i, j] = mat[i, j]);
      
    // Find the largest sum by considering all
    // possible next elements in sequence.
    int zzs = 0;
    for (int k = 0; k < n; k++)
        if (k != j)
            zzs = Math.Max(zzs, largestZigZagSumRec(mat,
                                    i + 1, k, n));
      
    return (dp[i, j] = (zzs + mat[i, j]));
}
  
// Returns largest possible sum of a Zizag sequence
// starting from top and ending at bottom.
static int largestZigZag(int [,]mat, int n)
{
    for (int i = 0; i < MAX; i++)
        for (int k = 0; k < MAX; k++)
                dp[i, k] = -1;
      
    // Consider all cells of top row as starting point
    int res = 0;
    for (int j = 0; j < n; j++)
        res = Math.Max(res, largestZigZagSumRec(mat,
                                        0, j, n));
    return res;
}
  
// Driver code
public static void Main(String[] args)
{
    int n = 3;
    int [,]mat = { {4, 2, 1},
                    {3, 9, 6},
                    {11, 3, 15}};
    Console.Write("Largest zigzag sum: " + 
                        largestZigZag(mat, n));
}
}
  
// This code is contributed by 29AjayKumar


输出:

Largest zigzag sum: 28

重叠子问题
考虑到以上实现,对于大小为3 x 3的矩阵mat [] [],以找到元素mat(i,j)的之字形和(zzs),形成以下递归树。

Recursion tree for cell (0, 0)
             zzs(0,0)                                
           /         \                               
    zzs(1,1)           zzs(1,2)                      
    /     \            /      \                      
zzs(2,0)  zzs(2,2)  zzs(2,0)  zzs(2,1)               


Recursion tree for cell (0, 1)
            zzs(0,1)
           /         \              
    zzs(1,0)          zzs(1,2)
    /     \            /      \    
zzs(2,1)  zzs(2,2)  zzs(2,0)  zzs(2,1)

Recursion tree for cell (0, 2)
             zzs(0,2)
           /         \                                             
    zzs(1,0)           zzs(1,1)                             
    /     \            /      \                             
 zzs(2,1)  zzs(2,2)  zzs(2,0)  zzs(2,2)

我们可以看到,有许多子问题一次又一次地得到解决。因此,此问题具有“重叠子结构”属性,可以通过使用“记忆化”或“制表”来避免相同子问题的重新计算。以下是LIS问题的列表化实施。

C++

// Memoization based C++ program to find the largest
// sum zigzag sequence
#include 
using namespace std;
  
const int MAX = 100;
int dp[MAX][MAX];
  
// Returns largest sum of a Zigzag sequence starting
// from (i, j) and ending at a bottom cell.
int largestZigZagSumRec(int mat[][MAX], int i,
                                int j, int n)
{
   if (dp[i][j] != -1)
      return dp[i][j];
  
   // If we have reached bottom
   if (i == n-1)
     return (dp[i][j] = mat[i][j]);
  
   // Find the largest sum by considering all
   // possible next elements in sequence.
   int zzs = 0;
   for (int k=0; k

Java

// Memoization based Java program to find the largest
// sum zigzag sequence
class GFG
{
  
static int MAX = 100;
static int [][]dp = new int[MAX][MAX];
  
// Returns largest sum of a Zigzag sequence starting
// from (i, j) and ending at a bottom cell.
static int largestZigZagSumRec(int mat[][], int i,
                                int j, int n)
{
    if (dp[i][j] != -1)
        return dp[i][j];
      
    // If we have reached bottom
    if (i == n - 1)
        return (dp[i][j] = mat[i][j]);
      
    // Find the largest sum by considering all
    // possible next elements in sequence.
    int zzs = 0;
    for (int k = 0; k < n; k++)
        if (k != j)
            zzs = Math.max(zzs, largestZigZagSumRec(mat,
                                    i + 1, k, n));
      
    return (dp[i][j] = (zzs + mat[i][j]));
}
  
// Returns largest possible sum of a Zizag sequence
// starting from top and ending at bottom.
static int largestZigZag(int mat[][], int n)
{
    for (int i = 0; i < MAX; i++)
        for (int k = 0; k < MAX; k++)
                dp[i][k] = -1;
      
    // Consider all cells of top row as starting point
    int res = 0;
    for (int j = 0; j < n; j++)
        res = Math.max(res, largestZigZagSumRec(mat,
                                           0, j, n));
      
    return res;
}
  
// Driver code
public static void main(String[] args)
{
    int n = 3;
    int mat[][] = { {4, 2, 1},
                    {3, 9, 6},
                    {11, 3, 15}};
    System.out.print("Largest zigzag sum: " + 
                        largestZigZag(mat, n));
}
}
  
// This code is contributed by PrinciRaj1992

Python3

# Memoization based Python3 program to find the largest
# sum zigzag sequence
MAX = 100;
  
dp = [[0 for i in range(MAX)] for j in range(MAX)]
  
# Returns largest sum of a Zigzag sequence starting
# from (i, j) and ending at a bottom cell.
def largestZigZagSumRec(mat, i, j, n):
    if (dp[i][j] != -1):
        return dp[i][j];
  
    # If we have reached bottom
    if (i == n - 1):
        dp[i][j] = mat[i][j];
        return (dp[i][j]);
  
    # Find the largest sum by considering all
    # possible next elements in sequence.
    zzs = 0;
    for k in range(n):
        if (k != j):
            zzs = max(zzs, largestZigZagSumRec(mat,
                     i + 1, k, n));
    dp[i][j] = (zzs + mat[i][j]);
    return (dp[i][j]);
  
# Returns largest possible sum of a Zizag sequence
# starting from top and ending at bottom.
def largestZigZag(mat, n):
    for i in range(MAX):
        for k in range(MAX):
            dp[i][k] = -1;
  
    # Consider all cells of top row as starting point
    res = 0;
    for j in range(n):
        res = max(res, largestZigZagSumRec(mat, 0, j, n));
  
    return res;
  
# Driver code
if __name__ == '__main__':
    n = 3;
    mat = [[4, 2, 1], [3, 9, 6], [11, 3, 15]];
    print("Largest zigzag sum: ", largestZigZag(mat, n));
  
# This code is contributed by Rajput-Ji

C#

// Memoization based C# program to find the largest
// sum zigzag sequence
using System;
  
class GFG
{
  
static int MAX = 100;
static int [,]dp = new int[MAX, MAX];
  
// Returns largest sum of a Zigzag sequence starting
// from (i, j) and ending at a bottom cell.
static int largestZigZagSumRec(int [,]mat, int i,
                                int j, int n)
{
    if (dp[i, j] != -1)
        return dp[i, j];
      
    // If we have reached bottom
    if (i == n - 1)
        return (dp[i, j] = mat[i, j]);
      
    // Find the largest sum by considering all
    // possible next elements in sequence.
    int zzs = 0;
    for (int k = 0; k < n; k++)
        if (k != j)
            zzs = Math.Max(zzs, largestZigZagSumRec(mat,
                                    i + 1, k, n));
      
    return (dp[i, j] = (zzs + mat[i, j]));
}
  
// Returns largest possible sum of a Zizag sequence
// starting from top and ending at bottom.
static int largestZigZag(int [,]mat, int n)
{
    for (int i = 0; i < MAX; i++)
        for (int k = 0; k < MAX; k++)
                dp[i, k] = -1;
      
    // Consider all cells of top row as starting point
    int res = 0;
    for (int j = 0; j < n; j++)
        res = Math.Max(res, largestZigZagSumRec(mat,
                                        0, j, n));
    return res;
}
  
// Driver code
public static void Main(String[] args)
{
    int n = 3;
    int [,]mat = { {4, 2, 1},
                    {3, 9, 6},
                    {11, 3, 15}};
    Console.Write("Largest zigzag sum: " + 
                        largestZigZag(mat, n));
}
}
  
// This code is contributed by 29AjayKumar

输出:

Largest zigzag sum: 28

参考:Directi中的要求