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

📅  最后修改于: 2021-04-22 02:25:31             🧑  作者: 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))


输出:
3