给定一个二维数组arr[][]和一块尺寸为N × M的巧克力棒,任务是通过将巧克力棒分成一块或多块来找到无效块区域的最小可能总和,其中如果巧克力块的尺寸与任何给定的对不匹配,则巧克力块被称为无效。
注意:一块巧克力可以垂直或水平切割(垂直于它的边),这样它就会被分成两块,并且给定向量中的维度没有排序,即给定向量中的一对 (x, y)维度 (x, y) 和 (y, x) 被认为是有效的。
例子:
Input: N = 10, M =10, arr[][] = {{1, 2}}
Output: 0
Explanation:
Divide the given chocolate bar of dimension (10, 10) into 50 pieces of dimension (1, 2) or (2, 1), not leaving any left over pieces, hence output is zero.
Input: N = 10, M =10, arr[][] = {{3, 5}}
Output: 10
朴素的方法:朴素的想法是使用递归通过进行所有可能的垂直或水平切割来在每个可能的维度上划分巧克力。请按照以下步骤解决此问题:
- 将巧克力棒分成所有可能的方式,即,将所有可能的垂直和水平切开,并针对每种情况递归地找到结果块的解决方案。
- 对于基本情况,只需检查当前除法是否有效:
- 如果有效则返回零。
- 否则,尝试使用上述方法将其划分为有效块,如果不能进一步划分为有效块,则返回该块的面积。
时间复杂度: O(N + M) (N + M)
辅助空间: O(1)
高效方法:为了优化上述方法的想法是使用动态编程的上述方法具有重叠子问题需要被不止一次,并减少计算中使用吨abulation或记忆化计算。可以制作的不同巧克力块的总数仅为N × M ,因此上述算法有 N × M 个状态。
请按照以下步骤解决问题:
- 初始化数组dp[][]以在dp[l][b]处存储minInvalidAreaUtil(l, b) ,ok[][]以在ok[i][j] 处存储有效维度的巧克力 (i, j) = 1和ok[j][i] = 1。
- 对于每个状态,当前块(l, b)在恒定时间内是否有效从查找表ok[][]
- 如果当前片段(l, b)有效,即ok[l][b] == 1 。因此,返回dp[l][b] = 0
- 否则,通过逐一进行所有可能的垂直和水平切割来计算它,并为每种情况找到结果碎片的解决方案。因此,更新dp[l][b]。
- 将最终答案打印为minInvalidAreaUtil(l, b)。
下面是上述方法的实现。
C++
// C++ program for the above approach
#include
using namespace std;
const int sz = 1001;
// Store valid dimensions
bool ok[sz][sz] = {};
// Stores memoization
int dp[sz][sz];
// Utility function to calculate minimum invalid area for
// Chocolate piece having dimension (l, r)
int minInvalidAreaUtil(int l, int b)
{
if (dp[l][b] == -1) {
// Check whether current piece is valid or not
// If it is, then return zero
// for current dimension
if (ok[l][b]) {
return dp[l][b] = 0;
}
int ans = l * b;
// Making all possible horizontal cuts, one by
// one and calculating the sum of minimum invalid
// area for both the resulting pieces
for (int i = 1; i < b; i++) {
ans = min(ans,
minInvalidAreaUtil(l, i)
+ minInvalidAreaUtil(l, b - i));
}
// Making all possible vertical cuts, one by one
// and calculating the sum of minimum invalid area
// for both the resulting pieces
for (int i = 1; i < l; i++) {
ans = min(ans,
minInvalidAreaUtil(i, b)
+ minInvalidAreaUtil(l - i, b));
}
// Store the computed result
dp[l][b] = ans;
}
return dp[l][b];
}
// Function to calculate minimum invalid area for
// Chocolate piece having dimension (l, r)
void minInvalidArea(int N, int M,
vector >& dimensions)
{
// Total number of valid dimensions
int K = dimensions.size();
// Storing valid dimensions as for every (x, y)
// both (x, y) and (y, x) are valid
for (int i = 0; i < K; i++) {
ok[dimensions[i].first][dimensions[i].second] = 1;
ok[dimensions[i].second][dimensions[i].first] = 1;
}
// Fill dp[][] table with -1, indicating that
// results are not computed yet
for (int i = 0; i < sz; i++) {
for (int j = 0; j < sz; j++) {
dp[i][j] = -1;
}
}
// Stores minimum area
int minArea = minInvalidAreaUtil(N, M);
// Print minArea as the output
cout << minArea << endl;
}
// Driver Code
int main()
{
// Given N & M
int N = 10, M = 10;
// Given valid dimensions
vector > dimensions = { { 3, 5 } };
// Function Call
minInvalidArea(N, M, dimensions);
return 0;
}
Java
// Java program for the above approach
import java.io.*;
import java.util.*;
class GFG{
static final int sz = 1001;
// Store valid dimensions
static boolean ok[][] = new boolean[sz][sz];
// Stores memoization
static int dp[][] = new int[sz][sz];
static class pair
{
int first, second;
public pair(int first, int second)
{
this.first = first;
this.second = second;
}
}
// Utility function to calculate minimum invalid
// area for Chocolate piece having dimension (l, r)
static int minInvalidAreaUtil(int l, int b)
{
if (dp[l][b] == -1)
{
// Check whether current piece is valid
// or not. If it is, then return zero
// for current dimension
if (ok[l][b])
{
return dp[l][b] = 0;
}
int ans = l * b;
// Making all possible horizontal cuts, one by
// one and calculating the sum of minimum invalid
// area for both the resulting pieces
for(int i = 1; i < b; i++)
{
ans = Math.min(ans,
minInvalidAreaUtil(l, i) +
minInvalidAreaUtil(l, b - i));
}
// Making all possible vertical cuts, one by one
// and calculating the sum of minimum invalid area
// for both the resulting pieces
for(int i = 1; i < l; i++)
{
ans = Math.min(ans,
minInvalidAreaUtil(i, b) +
minInvalidAreaUtil(l - i, b));
}
// Store the computed result
dp[l][b] = ans;
}
return dp[l][b];
}
// Function to calculate minimum invalid area for
// Chocolate piece having dimension (l, r)
static void minInvalidArea(int N, int M,
Vector dimensions)
{
// Total number of valid dimensions
int K = dimensions.size();
// Storing valid dimensions as for every (x, y)
// both (x, y) and (y, x) are valid
for(int i = 0; i < K; i++)
{
ok[dimensions.elementAt(i).first][dimensions.elementAt(i).second] = true;
ok[dimensions.elementAt(i).second][dimensions.elementAt(i).first] = true;
}
// Fill dp[][] table with -1, indicating that
// results are not computed yet
for(int i = 0; i < sz; i++)
{
for(int j = 0; j < sz; j++)
{
dp[i][j] = -1;
}
}
// Stores minimum area
int minArea = minInvalidAreaUtil(N, M);
// Print minArea as the output
System.out.println(minArea);
}
// Driver Code
public static void main(String[] args)
{
// Given N & M
int N = 10, M = 10;
// Given valid dimensions
Vector dimensions = new Vector<>();
dimensions.add(new pair(3, 5));
// Function Call
minInvalidArea(N, M, dimensions);
}
}
// This code is contributed by Dharanendra L V.
Python3
# Python3 program for the above approach
sz = 1001
# Store valid dimensions
ok = [[0 for i in range(sz)]
for i in range(sz)]
# Stores memoization
dp = [[0 for i in range(sz)]
for i in range(sz)]
# Utility function to calculate minimum
# invalid area for Chocolate piece having
# dimension (l, r)
def minInvalidAreaUtil(l, b):
global dp, ok
if (dp[l][b] == -1):
# Check whether current piece is valid
# or not If it is, then return zero
# for current dimension
if (ok[l][b]):
dp[l][b] = 0
return dp[l][b]
ans = l * b
# Making all possible horizontal cuts, one by
# one and calculating the sum of minimum invalid
# area for both the resulting pieces
for i in range(1, b):
ans = min(ans, minInvalidAreaUtil(l, i) +
minInvalidAreaUtil(l, b - i))
# Making all possible vertical cuts, one by one
# and calculating the sum of minimum invalid area
# for both the resulting pieces
for i in range(1, l):
ans = min(ans, minInvalidAreaUtil(i, b) +
minInvalidAreaUtil(l - i, b))
# Store the computed result
dp[l][b] = ans
return dp[l][b]
# Function to calculate minimum invalid area for
# Chocolate piece having dimension (l, r)
def minInvalidArea(N, M, dimensions):
global dp, ok
# Total number of valid dimensions
K = len(dimensions)
# Storing valid dimensions as for every (x, y)
# both (x, y) and (y, x) are valid
for i in range(K):
ok[dimensions[i][0]][dimensions[i][1]] = 1
ok[dimensions[i][1]][dimensions[i][0]] = 1
# Fill dp[][] table with -1, indicating that
# results are not computed yet
for i in range(sz):
for j in range(sz):
dp[i][j] = -1
# Stores minimum area
minArea = minInvalidAreaUtil(N, M)
# PrminArea as the output
print(minArea)
#Driver Code
if __name__ == '__main__':
# Given N & M
N, M = 10, 10
# Given valid dimensions
dimensions = [ [ 3, 5 ] ]
# Function Call
minInvalidArea(N, M, dimensions)
# This code is contributed by mohit kumar 29
10
时间复杂度: O(N * M * (N + M))
辅助空间: O(N * M)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。