Open In App

Paper Cut into Minimum Number of Squares

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given a paper of size, A x B. Task is to cut the paper into squares of any size. Find the minimum number of squares that can be cut from the paper. 
Examples: 
 

Input  : 13 x 29
Output : 9
Explanation :
2 (squares of size 13x13) +
4 (squares of size 3x3) +
3 (squares of size 1x1)=9
Input : 4 x 5
Output : 5
Explanation :
1 (squares of size 4x4) +
4 (squares of size 1x1)

 

We know that if we want to cut a minimum number of squares from the paper then we would have to cut the largest square possible from the paper first and the largest square will have the same side as the smaller side of the paper. For example, if the paper has the size 13 x 29, then the maximum square will be of side 13. so we can cut 2 square of size 13 x 13 (29/13 = 2). Now remaining paper will have size 3 x 13. Similarly, we can cut the remaining paper by using 4 squares of size 3 x 3 and 3 squares of 1 x 1. So a minimum of 9 squares can be cut from the Paper of size 13 x 29.
 

dig1

Below is the implementation of the above approach. 
 

C++




// C++ program to find minimum number of squares
// to cut a paper.
#include<bits/stdc++.h>
using namespace std;
 
// Returns min number of squares needed
int minimumSquare(int a, int b)
{
    long long result = 0, rem = 0;
 
    // swap if a is small size side .
    if (a < b)
        swap(a, b);
 
    // Iterate until small size side is
    // greater than 0
    while (b > 0)
    {
        // Update result
        result += a/b;
 
        long long rem = a % b;
        a = b;
        b = rem;
    }
 
    return result;
}
 
// Driver code
int main()
{
    int n = 13, m = 29;
    cout << minimumSquare(n, m);
    return 0;
}


Java




// Java program to find minimum
// number of squares to cut a paper.
class GFG{
     
// To swap two numbers
static void swap(int a,int b)
{
    int temp = a;
    a = b;
    b = temp;
}
 
// Returns min number of squares needed
static int minimumSquare(int a, int b)
{
    int result = 0, rem = 0;
 
    // swap if a is small size side .
    if (a < b)
        swap(a, b);
 
    // Iterate until small size side is
    // greater than 0
    while (b > 0)
    {
        // Update result
        result += a/b;
        rem = a % b;
        a = b;
        b = rem;
    }
 
    return result;
}
 
// Driver code
public static void main(String[] args)
{
    int n = 13, m = 29;
    System.out.println(minimumSquare(n, m));
}
}
 
//This code is contributed by Smitha Dinesh Semwal.


Python3




# Python 3 program to find minimum
# number of squares to cut a paper.
 
# Returns min number of squares needed
def minimumSquare(a, b):
 
    result = 0
    rem = 0
 
    # swap if a is small size side .
    if (a < b):
        a, b = b, a
 
    # Iterate until small size side is
    # greater than 0
    while (b > 0):
     
        # Update result
        result += int(a / b)
 
        rem = int(a % b)
        a = b
        b = rem
 
    return result
 
# Driver code
n = 13
m = 29
 
print(minimumSquare(n, m))
 
# This code is contributed by
# Smitha Dinesh Semwal


C#




// C# program to find minimum
// number of squares to cut a paper.
using System;
     
class GFG
{
     
// To swap two numbers
static void swap(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
}
 
// Returns min number of squares needed
static int minimumSquare(int a, int b)
{
    int result = 0, rem = 0;
 
    // swap if a is small size side .
    if (a < b)
        swap(a, b);
 
    // Iterate until small size side is
    // greater than 0
    while (b > 0)
    {
        // Update result
        result += a / b;
        rem = a % b;
        a = b;
        b = rem;
    }
    return result;
}
 
// Driver code
public static void Main(String[] args)
{
    int n = 13, m = 29;
    Console.WriteLine(minimumSquare(n, m));
}
}
 
// This code is contributed by 29AjayKumar


Javascript




<script>
 
// Javascript program to find
// minimum number of squares
// to cut a paper.
 
// Returns min number of squares needed
function minimumSquare(a, b)
{
    let result = 0, rem = 0;
 
    // swap if a is small size side .
    if (a < b) {
        let temp = a;
        a = b;
        b = temp;
    }
 
    // Iterate until small size side is
    // greater than 0
    while (b > 0)
    {
        // Update result
        result += parseInt(a/b);
 
        let rem = a % b;
        a = b;
        b = rem;
    }
 
    return result;
}
 
// Driver code
    let n = 13, m = 29;
    document.write(minimumSquare(n, m));
 
</script>


Output: 

9

Time Complexity: O(log(min(a,b))) 
Auxiliary Space: O(1)

Note that the above Greedy solution doesn’t always produce an optimal result. For example, if the input is 36 x 30, the above algorithm would produce output 6, but we can cut the paper into 5 squares 
1) Three squares of size 12 x 12 
2) Two squares of size 18 x 18.

Thanks to Sergey V. Pereslavtsev for pointing out the above case.

New Approach:-  Here, Another approach to solve the problem of cutting a paper into the minimum number of squares is to use dynamic programming. We can create a 2D table where the rows represent the possible sizes of the paper and the columns represent the size of the square we want to cut. Then we can fill the table bottom-up, starting from the smallest paper size and the smallest square size, and using the previous values to compute the optimal solution for the current paper size and square size.

Let’s say we have a paper of size n x m, and we want to find the minimum number of squares we can cut from it. We can define a function f(i, j) that represents the minimum number of squares we can cut from a paper of size i x j. Then the recurrence relation can be written as:

f(i, j) = min(f(i-k, j) + f(k, j)) for k in range(1, i)
+ min(f(i, j-k) + f(i, k)) for k in range(1, j)
+ 1 if i == j

The first two terms correspond to cutting the paper horizontally and vertically, and the last term corresponds to cutting a square of size i x i (or j x j) from the paper. We can use this recurrence relation to fill the table, and the optimal solution will be in the bottom-right corner.

Below is the implementation of the dynamic programming approach:

C++




#include <iostream>
#include <vector>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the minimum number of
// squares required to fill an n x m rectangle
int minimumSquare(int n, int m) {
    // Create a 2D DP array to store the minimum squares required
    vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
     
    // Loop through rows and columns
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (i == j) {
                // If the rectangle is already a
                // square, one square is needed
                dp[i][j] = 1;
            } else {
                // Initialize with maximum value
                dp[i][j] = INT_MAX;
                // Try all possible splits and find the minimum
                for (int k = 1; k < i; k++) {
                    dp[i][j] = min(dp[i][j], dp[i - k][j] + dp[k][j]);
                }
                for (int k = 1; k < j; k++) {
                    dp[i][j] = min(dp[i][j], dp[i][j - k] + dp[i][k]);
                }
            }
        }
    }
    return dp[n][m];
}
 
int main() {
    int n = 13;
    int m = 29;
    cout << minimumSquare(n, m) << endl;  // Output: 9
    return 0;
}


Java




public class Main {
    // Function to find the minimum number of
    // squares required to fill an n x m rectangle
    public static int minimumSquare(int n, int m) {
        // Create a 2D DP array to store the minimum squares required
        int[][] dp = new int[n + 1][m + 1];
         
        // Loop through rows and columns
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (i == j) {
                    // If the rectangle is already a square, one square is needed
                    dp[i][j] = 1;
                } else {
                    // Initialize with maximum value
                    dp[i][j] = Integer.MAX_VALUE;
                    // Try all possible splits and find the minimum
                    for (int k = 1; k < i; k++) {
                        dp[i][j] = Math.min(dp[i][j], dp[i - k][j] + dp[k][j]);
                    }
                    for (int k = 1; k < j; k++) {
                        dp[i][j] = Math.min(dp[i][j], dp[i][j - k] + dp[i][k]);
                    }
                }
            }
        }
        return dp[n][m];
    }
 
    public static void main(String[] args) {
        int n = 13;
        int m = 29;
        System.out.println(minimumSquare(n, m));  // Output: 9
    }
}


Python




def minimumSquare(n, m):
    # Create a 2D DP array to store the minimum squares required
    dp = [[float('inf')] * (m + 1) for _ in range(n + 1)]
     
    # Loop through rows and columns
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            if i == j:
                # If the rectangle is already a square, one square is needed
                dp[i][j] = 1
            else:
                # Initialize with maximum value
                dp[i][j] = float('inf')
                # Try all possible splits and find the minimum
                for k in range(1, i):
                    dp[i][j] = min(dp[i][j], dp[i - k][j] + dp[k][j])
                for k in range(1, j):
                    dp[i][j] = min(dp[i][j], dp[i][j - k] + dp[i][k])
    return dp[n][m]
 
n = 13
m = 29
print(minimumSquare(n, m))  # Output: 9


C#




using System;
 
public class MainClass {
    // Function to find the minimum number of
    // squares required to fill an n x m rectangle
    public static int MinimumSquare(int n, int m) {
        // Create a 2D DP array to store the minimum squares required
        int[,] dp = new int[n + 1, m + 1];
         
        // Loop through rows and columns
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (i == j) {
                    // If the rectangle is already a square,
                    // one square is needed
                    dp[i, j] = 1;
                } else {
                    // Initialize with maximum value
                    dp[i, j] = int.MaxValue;
                    // Try all possible splits and find the minimum
                    for (int k = 1; k < i; k++) {
                        dp[i, j] = Math.Min(dp[i, j], dp[i - k, j] + dp[k, j]);
                    }
                    for (int k = 1; k < j; k++) {
                        dp[i, j] = Math.Min(dp[i, j], dp[i, j - k] + dp[i, k]);
                    }
                }
            }
        }
        return dp[n, m];
    }
 
    public static void Main(string[] args) {
        int n = 13;
        int m = 29;
        Console.WriteLine(MinimumSquare(n, m));  // Output: 9
    }
}


Javascript




function minimumSquare(n, m) {
    // Create a 2D DP array to store the minimum squares required
    const dp = new Array(n + 1).fill().map(() => new Array(m + 1).fill(0));
     
    // Loop through rows and columns
    for (let i = 1; i <= n; i++) {
        for (let j = 1; j <= m; j++) {
            if (i === j) {
                // If the rectangle is already a square,
                // one square is needed
                dp[i][j] = 1;
            } else {
                // Initialize with maximum value
                dp[i][j] = Number.MAX_VALUE;
                // Try all possible splits and find the minimum
                for (let k = 1; k < i; k++) {
                    dp[i][j] = Math.min(dp[i][j], dp[i - k][j] + dp[k][j]);
                }
                for (let k = 1; k < j; k++) {
                    dp[i][j] = Math.min(dp[i][j], dp[i][j - k] + dp[i][k]);
                }
            }
        }
    }
    return dp[n][m];
}
 
const n = 13;
const m = 29;
console.log(minimumSquare(n, m));  // Output: 9


Output:-

9

Time Complexity:- The time complexity of the dynamic programming approach implemented here is O(n^3), where n is the maximum of the two sides of the paper, i.e., the value of max(n, m). This is because there are two nested loops iterating over the two dimensions of the dp table, and an additional inner loop iterating over the possible sub-sizes of the squares.

Auxiliary Space:- The auxiliary space used by the algorithm is O(n^2), as we are using a 2D array of size (n+1) x (m+1) to store the intermediate results of the subproblems.
 



Last Updated : 13 Sep, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads