📜  矩阵中最大和的锯齿形序列

📅  最后修改于: 2021-09-17 07:17:44             🧑  作者: Mango

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

例子:

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


Javascript


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


Javascript


输出:

Largest zigzag sum: 28

重叠子问题
考虑上述实现,对于大小为 3 x 3 的矩阵 mat[][],为了找到元素 mat(i,j) 的 zigzag sum(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)

我们可以看到有很多子问题被一次又一次地解决了。所以这个问题具有重叠子结构的性质,并且可以通过使用 Memoization 或 Tabulation 来避免相同子问题的重新计算。以下是 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

蟒蛇3

# 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

Javascript


输出:

Largest zigzag sum: 28

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程