📜  将巧克力棒分成小块,尽量减少无效块的面积

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

给定一个二维数组arr[][]和一块尺寸为N × M的巧克力棒,任务是通过将巧克力棒分成一块或多块来找到无效块区域的最小可能总和,其中如果巧克力块的尺寸与任何给定的对不匹配,则巧克力块被称为无效。

注意:一块巧克力可以垂直或水平切割(垂直于它的边),这样它就会被分成两块,并且给定向量中的维度没有排序,即给定向量中的一对 (x, y)维度 (x, y) 和 (y, x) 被认为是有效的。

例子:

朴素的方法:朴素的想法是使用递归通过进行所有可能的垂直或水平切割来在每个可能的维度上划分巧克力。请按照以下步骤解决此问题:

  • 将巧克力棒分成所有可能的方式,即,将所有可能的垂直和水平切开,并针对每种情况递归地找到结果块的解决方案。
  • 对于基本情况,只需检查当前除法是否有效:
    • 如果有效则返回零。
    • 否则,尝试使用上述方法将其划分为有效块,如果不能进一步划分为有效块,则返回该块的面积。

时间复杂度: 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) = 1ok[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 现场工作专业课程学生竞争性编程现场课程