📌  相关文章
📜  切割矩阵的方式数量,使得每个部分至少填充一个单元格

📅  最后修改于: 2021-09-06 06:42:40             🧑  作者: Mango

给定一个整数K和一个包含 1 和 0 的矩阵mat[][] ,其中 1 表示单元格已填充,0 表示空单元格。任务是找到使用K-1次切割将矩阵切割成K 个部分的方法的数量,使得矩阵的每个部分至少包含一个填充单元格。

例子:

方法:这个想法是使用动态规划来计算切割至少一个填充单元格的矩阵的方法数。

  • 计算矩阵的前缀和,以便我们可以在 O(1) 时间内计算矩阵的特定部分是否包含填充单元格。
  • 定义一个dp表来存储K份披萨的切法数,其中dp[k][r]表示将矩阵从左上角到R行C列切为K份的方法数。
  • 最后,迭代每个可能的矩阵并检查矩阵是否可以分为两个部分,直到该索引为止,并且这两个部分是否有效。

下面是上述方法的实现:

C++
// CPP implementation to find the
// number of ways to cut the matrix
// into the K parts such that each
// part have atleast one filled cell
#include 
using namespace std;
 
// Function  to find the number of
// ways to cut the matrix into the
// K parts such that each part have
// atleast one filled cell
int ways(vector> &arr, int K)
{
  int R = arr.size();
  int C = arr[0].size();
 
  int preSum[R][C];
 
  // Loop to find prefix sum of the
  // given matrix
  for (int r = R - 1; r >= 0; r--)
  {
    for (int c = C - 1; c >= 0; c--)
    {
      preSum[r] = arr[r];
 
      if (r + 1 < R) preSum[r] += preSum[r + 1];
 
      if (c + 1 < C) preSum[r] += preSum[r];
 
      if (r + 1 < R && c + 1 < C) preSum[r] -= preSum[r + 1];
    }
  }
 
  // dp(r, c, 1) = 1
  // if preSum[r] else 0
  int dp[K + 1][R][C];
 
  // Loop to iterate over the dp
  // table of the given matrix
  for (int k = 1; k <= K; k++)
  {
    for (int r = R - 1; r >= 0; r--)
    {
      for (int c = C - 1; c >= 0; c--)
      {
        if (k == 1)
        {
          dp[k][r] = (preSum[r] > 0) ? 1 : 0;
        } else {
          dp[k][r] = 0;
          for (int r1 = r + 1; r1 < R; r1++)
          {
 
            // Check if can cut horizontally
            // at r1, at least one apple in
            // matrix (r, c) -> r1, C-1
            if (preSum[r] - preSum[r1] > 0)
              dp[k][r] += dp[k - 1][r1];
          }
          for (int c1 = c + 1; c1 < C; c1++)
          {
 
            // Check if we can cut vertically
            // at c1, at least one apple in
            // matrix (r, c) -> R-1, c1
            if (preSum[r] - preSum[r][c1] > 0)
              dp[k][r] += dp[k - 1][r][c1];
          }
        }
      }
    }
  }
  return dp[K][0][0];
}
 
// Driver code
int main()
{
  vector> arr = {{1, 0, 0}, {1, 1, 1}, {0, 0, 0}};
  int k = 3;
 
  // Function Call
  cout << ways(arr, k) << endl;
  return 0;
}
 
// This code is contributed by sanjeev2552


Java
// Java implementation to find the 
// number of ways to cut the matrix 
// into the K parts such that each
// part have atleast one filled cell
import java.util.*;
import java.lang.*;
import java.io.*;
 
class GFG{
 
// Function  to find the number of
// ways to cut the matrix into the
// K parts such that each part have
// atleast one filled cell    
static int ways(int[][] arr, int K)
{
    int R = arr.length;
    int C = arr[0].length;
     
    int[][] preSum = new int[R][C];
     
    // Loop to find prefix sum of the 
    // given matrix
    for(int r = R - 1; r >= 0; r--)
    {
        for(int c = C - 1; c >= 0; c--)
        {
            preSum[r] = arr[r];
             
            if (r + 1 < R)
            preSum[r] += preSum[r + 1];
             
            if (c + 1 < C)
            preSum[r] += preSum[r];
             
            if (r + 1 < R && c + 1 < C)
            preSum[r] -= preSum[r + 1];
        }
    }
     
    // dp(r, c, 1) = 1 
    // if preSum[r] else 0
    int[][][] dp = new int[K + 1][R][C];
     
    // Loop to iterate over the dp 
    // table of the given matrix
    for(int k = 1; k <= K; k++)
    {
        for(int r = R - 1; r >= 0; r--)
        {
            for(int c = C - 1; c >= 0; c--)
            {
                if (k == 1)
                {
                    dp[k][r] = (preSum[r] > 0) ?
                                              1 : 0;
                }
                else
                {
                    dp[k][r] = 0;
                    for(int r1 = r + 1; r1 < R; r1++)
                    {
                         
                        // Check if can cut horizontally
                        // at r1, at least one apple in 
                        // matrix (r, c) -> r1, C-1
                        if (preSum[r] - preSum[r1] > 0)
                             dp[k][r] += dp[k - 1][r1];
                    }
                    for(int c1 = c + 1; c1 < C; c1++)
                    {
                     
                        // Check if we can cut vertically 
                        // at c1, at least one apple in 
                        // matrix (r, c) -> R-1, c1
                        if (preSum[r] - preSum[r][c1] > 0)
                            dp[k][r] += dp[k - 1][r][c1];
                    }
                }
            }
        }
    }
    return dp[K][0][0];
}
 
// Driver code
public static void main(String[] args)
{
    int[][] arr = { { 1, 0, 0 },
                    { 1, 1, 1 },
                    { 0, 0, 0 } };
    int k = 3;
       
    // Function Call
    System.out.println(ways(arr, k));
}
}
 
// This code is contributed by offbeat


Python3
# Python3 implementation to find the
# number of ways to cut the matrix
# into the K parts such that each
# part have atleast one filled cell
 
# Function  to find the
# number of ways to cut the matrix
# into the K parts such that each
# part have atleast one filled cell
def ways(arr, k):
    R = len(arr)
    C = len(arr[0])
    K = k
    preSum = [[0 for _ in range(C)]\
                 for _ in range(R)]
                  
    # Loop to find prefix sum of the
    # given matrix
    for r in range(R-1, -1, -1):
        for c in range(C-1, -1, -1):
            preSum[r] = arr[r]
             
            if r + 1 < R:
                preSum[r] += preSum[r + 1]
            if c + 1 < C:
                preSum[r] += preSum[r]
                 
            if r + 1 < R and c + 1 < C:
                preSum[r] -= preSum[r + 1]
     
    # dp(r, c, 1) = 1
    # if preSum[r] else 0
    dp = [[[0 for _ in range(C)]\
              for _ in range(R)]\
              for _ in range(K + 1)]
               
    # Loop to iterate over the dp
    # table of the given matrix
    for k in range(1, K + 1):
        for r in range(R-1, -1, -1):
            for c in range(C-1, -1, -1):
                if k == 1:
                    dp[k][r] = 1 \
                        if preSum[r] > 0\
                        else 0
                else:
                    dp[k][r] = 0
                    for r1 in range(r + 1, R):
                         
                        # Check if can cut horizontally
                        # at r1, at least one apple in
                        # matrix (r, c) -> r1, C-1
                        if preSum[r] - preSum[r1] > 0:
                            dp[k][r] += dp[k-1][r1]
                    for c1 in range(c + 1, C):
                         
                        # Check if we can cut vertically
                        # at c1, at least one apple in
                        # matrix (r, c) -> R-1, c1
                        if preSum[r] - preSum[r][c1] > 0:
                            dp[k][r] += dp[k-1][r][c1]
    return dp[K][0][0]
     
# Driver Code
if __name__ == "__main__":
    arr = [[1, 0, 0], [1, 1, 1], [0, 0, 0]]
    k = 3
     
    # Function Call
    print(ways(arr, k))


C#
// C# implementation to find the
// number of ways to cut the matrix
// into the K parts such that each
// part have atleast one filled cell
using System;
class GFG {
 
    // Function  to find the number of
    // ways to cut the matrix into the
    // K parts such that each part have
    // atleast one filled cell
    static int ways(int[, ] arr, int K)
    {
        int R = arr.GetLength(0);
        int C = arr.GetLength(1);
 
        int[, ] preSum = new int[R, C];
 
        // Loop to find prefix sum of the
        // given matrix
        for (int r = R - 1; r >= 0; r--) {
            for (int c = C - 1; c >= 0; c--) {
                preSum[r, c] = arr[r, c];
 
                if (r + 1 < R)
                    preSum[r, c] += preSum[r + 1, c];
 
                if (c + 1 < C)
                    preSum[r, c] += preSum[r, c + 1];
 
                if (r + 1 < R && c + 1 < C)
                    preSum[r, c] -= preSum[r + 1, c + 1];
            }
        }
 
        // dp(r, c, 1) = 1
        // if preSum[r] else 0
        int[, , ] dp = new int[K + 1, R, C];
 
        // Loop to iterate over the dp
        // table of the given matrix
        for (int k = 1; k <= K; k++) {
            for (int r = R - 1; r >= 0; r--) {
                for (int c = C - 1; c >= 0; c--) {
                    if (k == 1) {
                        dp[k, r, c]
                            = (preSum[r, c] > 0) ? 1 : 0;
                    }
                    else {
                        dp[k, r, c] = 0;
                        for (int r1 = r + 1; r1 < R; r1++) {
 
                            // Check if can cut horizontally
                            // at r1, at least one apple in
                            // matrix (r, c) -> r1, C-1
                            if (preSum[r, c] - preSum[r1, c]
                                > 0)
                                dp[k, r, c]
                                    += dp[k - 1, r1, c];
                        }
                        for (int c1 = c + 1; c1 < C; c1++) {
 
                            // Check if we can cut
                            // vertically at c1, at least
                            // one apple in matrix (r, c) ->
                            // R-1, c1
                            if (preSum[r, c] - preSum[r, c1]
                                > 0)
                                dp[k, r, c]
                                    += dp[k - 1, r, c1];
                        }
                    }
                }
            }
        }
        return dp[K, 0, 0];
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        int[, ] arr
            = { { 1, 0, 0 }, { 1, 1, 1 }, { 0, 0, 0 } };
        int k = 3;
 
        // Function Call
        Console.WriteLine(ways(arr, k));
    }
}
 
// This code is contributed by ukasp.


Javascript


输出:
3

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live