# Divide chocolate bar into pieces, minimizing the area of invalid pieces

• Difficulty Level : Hard
• Last Updated : 17 Jun, 2022

Given a 2d array, arr[][] and a piece of the chocolate bar of dimension N × M, the task is to find the minimum possible sum of the area of invalid pieces by dividing the chocolate bar into one or more pieces where a chocolate piece is called invalid if the dimension of that piece doesn’t match any given pair.

Note: A chocolate piece can be cut vertically or horizontally (perpendicular to its sides), such that it is divided into two pieces and the dimension in the given vector is not ordered i.e. for a pair (x, y) in the given vector both dimensions (x, y) and (y, x) are considered valid.

Examples:

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

Naive Approach: The naive idea is to use recursion to divide the chocolate in every possible dimension by making every possible vertical or horizontal cut. Follow the below steps to solve this problem:

• Divide the chocolate bar into all possible ways, i.e. make every possible vertical & horizontal cut one by one and for each case find a solution for the resulting pieces recursively.
• For the base case, simply check if the current division is valid or not:
• If it is valid then return zero.
• Otherwise, try to divide it into valid pieces using the above approach, if it cannot be divided further into valid pieces return the area of the piece.

Time Complexity: O(N + M)(N + M)
Auxiliary Space: O(1)

Efficient Approach: To optimize the above approach the idea is to use dynamic programming as the above approach has overlapping subproblems that need to be calculated more than once and to reduce that calculation use tabulation or memoization. The total number of different chocolate pieces that can be made is N × M only, so the above algorithm has N × M states.

Follow the steps below to solve the problem:

• Initialize an array dp[][] to store the minInvalidAreaUtil(l, b) at dp[l][b], ok[][] to store the valid dimension chocolates (i, j) in ok[i][j] = 1 and ok[j][i] = 1.
• For every state whether the current piece (l, b) is valid or not in constant time from lookup table ok[][]
• If the current piece (l, b) is valid, i.e ok[l][b] == 1. Therefore, return dp[l][b] = 0
• Otherwise, compute it by making every possible vertical & horizontal cut one by one and for each case find a solution for the resulting pieces. Hence, update dp[l][b].
• Print the final answer as minInvalidAreaUtil(l, b).

Below is the implementation of the above approach.

## 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`

## C#

 `// C# program to implement above approach``using` `System;``using` `System.Collections.Generic;` `class` `GFG``{` `  ``static` `int` `sz = 1001;` `  ``// Store valid dimensions``  ``static` `bool``[][] ok = ``new` `bool``[sz][];` `  ``// Stores memoization``  ``static` `int``[][] dp = ``new` `int``[sz][];` `  ``// 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, List dimensions)``  ``{` `    ``// Total number of valid dimensions``    ``int` `K = dimensions.Count;` `    ``// 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] = ``true``;``      ``ok[dimensions[i].second][dimensions[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``    ``Console.Write(minArea);``  ``}` `  ``// Driver Code``  ``public` `static` `void` `Main(``string``[] args){` `    ``int` `N = 10, M = 10;` `    ``for``(``int` `i = 0 ; i < sz ; i++){``      ``ok[i] = ``new` `bool``[sz];``      ``dp[i] = ``new` `int``[sz];``    ``}` `    ``// Given valid dimensions``    ``List dimensions = ``new` `List();``    ``dimensions.Add(``new` `pair(3, 5));` `    ``// Function Call``    ``minInvalidArea(N, M, dimensions);` `  ``}``}` `class` `pair``{``  ``public` `int` `first, second;` `  ``public` `pair(``int` `first, ``int` `second)``  ``{``    ``this``.first = first;``    ``this``.second = second;``  ``}``}` `// This code is contributed by subhamgoyal2014.`

## Javascript

 ``

Output

`10`

Time Complexity: O(N * M * (N + M))
Auxiliary Space: O(N * M)

My Personal Notes arrow_drop_up