给定一个整数K和一个包含 1 和 0 的矩阵mat[][] ,其中 1 表示单元格已填充,0 表示空单元格。任务是找到使用K-1次切割将矩阵切割成K 个部分的方法的数量,使得矩阵的每个部分至少包含一个填充单元格。
For each cut, there must be a direction either horizontal or vertical. Then you choose a cut position at the cell boundary and cut the matrix into two parts. If you cut the matrix vertically, the left part of the matrix will not be used again for further process. If you cut the matrix horizontally, the upper part of the matrix will not be used again.
例子:
Input: mat[][] = {{1, 0, 0}, {1, 1, 1}, {0, 0, 0}}, K = 3
Output: 3
Explantion:
Input: matrix = {{1, 0, 0}, {1, 1, 0}, {0, 0, 0}}, K = 3
Output: 1
方法:这个想法是使用动态规划来计算切割至少一个填充单元格的矩阵的方法数。
- 计算矩阵的前缀和,以便我们可以在 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