CSES Solutions - Rectangle Cutting
Last Updated :
08 Apr, 2024
Given an A X B rectangle, your task is to cut it into squares. On each move you can select a rectangle and cut it into two rectangles in such a way that all side lengths remain integers. What is the minimum possible number of moves?
Examples:
Input: A = 3, B = 5
Output: 3
Explanation: The three moves required to cut the rectangle into squares are:
- Cut the 3 X 5 rectangle into a square of size 3 X 3 and a rectangle of size 2 X 3.
- Cut the 2 X 3 rectangle into a square of size 2 X 2 and a rectangle of size 2 X 1.
- Cut the 2 X 1 rectangle into two squares of size 1 X 1.
Input: A = 5, B = 10
Output: 1
Explanation: Only 1 move is required to cut the rectangle into squares and that is by cutting the 5 X 10 rectangle into 2 squares of size 5 X 5.
Approach: To solve the problem, follow the below idea:
Maintain a dp[][] array such that dp[i][j] stores the minimum number of cuts required to cut an (i X j) rectangle into squares. For an (i X j) rectangle, there can be two cases:
- Case 1: If (i == j), then the rectangle is already a square. So, dp[i][j] = 0.
- Case 2: If (i != j), then we need to make the cut either horizontally or vertically.
- If we make the cut horizontally, then we can cut at any position 1, 2 ... i-1. If we cut at position k, then we are left with two pieces of sizes k X j and (i−k) X j. Now, we can look up the number of moves to reduce these to squares in the dp[][] array. We can iterate over all possible values of k and find the cut which requires minimum number of moves, that is dp[i][j] = min(dp[i][j], dp[i][k] + dp[i][j - k] + 1)
- Similarly, if we make the cut vertically, then we can cut at any position 1, 2 ... j-1. If we cut at position k, then we are left with two pieces of sizes i X k and i X (j - k). Now, we can look up the number of moves to reduce these to squares in the dp[][] array. We can iterate over all possible values of k and find the cut which requires minimum number of moves, that is dp[i][j] = min(dp[i][j], dp[k][j] + dp[i - k][j] + 1)
After considering over all the possible cuts, dp[A][B] stores the final answer.
Step-by-step algorithm:
- Initialize a dp[][] array with a very large number, say 10^9 such that dp[i][j] stores the minimum number of cuts required to cut an (i X j) rectangle into squares.
- Iterate over all the possible cuts we can make horizontally and iterate over all the cuts we can make vertically.
- If the length and breadth of the rectangle is 0 (i == j), then dp[i][j] = 0.
- Otherwise choose the horizontal or vertical cut which requires minimum total moves to reduce the rectangle to squares.
- Return the final answer as dp[A][B].
Below is the implementation of the algorithm:
C++
#include <bits/stdc++.h>
#define ll long long
using namespace std;
// Function to find the minimum number of moves required to
// cut a rectangle of A X B into squares
ll solve(ll A, ll B)
{
// dp[][] table such that dp[i][j] stores the minimum
// number of cuts required to cut a rectangle of size (i
// X j) into squares
vector<vector<int> > dp(A + 1, vector<int>(B + 1, 1e9));
for (int i = 0; i <= A; i++) {
for (int j = 0; j <= B; j++) {
// If the rectangle is already a square, then 0
// cuts are required
if (i == j) {
dp[i][j] = 0;
}
else {
// Iterate over all the possible cuts we can
// make horizontally
for (int k = 1; k < j; k++) {
dp[i][j]
= min(dp[i][j],
dp[i][k] + dp[i][j - k] + 1);
}
// Iterate over all the possible cuts we can
// make vertically
for (int k = 1; k < i; k++) {
dp[i][j]
= min(dp[i][j],
dp[k][j] + dp[i - k][j] + 1);
}
}
}
}
// Return the minimum number of cuts required to cut a
// rectangle of size (A X B) into squares
return dp[A][B];
}
int main()
{
// Sample Input
int A = 3, B = 5;
cout << solve(A, B) << "\n";
}
Java
import java.util.Arrays;
public class RectangleCutting {
// Function to find the minimum number of moves required to
// cut a rectangle of A X B into squares
static long solve(long A, long B) {
// dp[][] table such that dp[i][j] stores the minimum
// number of cuts required to cut a rectangle of size (i
// X j) into squares
long[][] dp = new long[(int) (A + 1)][(int) (B + 1)];
for (int i = 0; i <= A; i++) {
Arrays.fill(dp[i], Integer.MAX_VALUE);
}
for (int i = 0; i <= A; i++) {
for (int j = 0; j <= B; j++) {
// If the rectangle is already a square, then 0
// cuts are required
if (i == j) {
dp[i][j] = 0;
} else {
// Iterate over all the possible cuts we can
// make horizontally
for (int k = 1; k < j; k++) {
dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[i][j - k] + 1);
}
// Iterate over all the possible cuts we can
// make vertically
for (int k = 1; k < i; k++) {
dp[i][j] = Math.min(dp[i][j], dp[k][j] + dp[i - k][j] + 1);
}
}
}
}
// Return the minimum number of cuts required to cut a
// rectangle of size (A X B) into squares
return dp[(int) A][(int) B];
}
public static void main(String[] args) {
// Sample Input
int A = 3, B = 5;
System.out.println(solve(A, B));
}
}
// This code is contributed by shivamgupta0987654321
Python3
# Function to find the minimum number of moves required to
# cut a rectangle of A X B into squares
def solve(A, B):
# dp[][] table such that dp[i][j] stores the minimum
# number of cuts required to cut a rectangle of size (i
# X j) into squares
dp = [[float('inf')] * (B + 1) for _ in range(A + 1)]
for i in range(A + 1):
for j in range(B + 1):
# If the rectangle is already a square, then 0
# cuts are required
if i == j:
dp[i][j] = 0
else:
# Iterate over all the possible cuts we can
# make horizontally
for k in range(1, j):
dp[i][j] = min(dp[i][j], dp[i][k] + dp[i][j - k] + 1)
# Iterate over all the possible cuts we can
# make vertically
for k in range(1, i):
dp[i][j] = min(dp[i][j], dp[k][j] + dp[i - k][j] + 1)
# Return the minimum number of cuts required to cut a
# rectangle of size (A X B) into squares
return dp[A][B]
# Sample Input
A = 3
B = 5
print(solve(A, B))
JavaScript
// Function to find the minimum number of moves required to
// cut a rectangle of A X B into squares
function solve(A, B) {
// Create a dp table such that dp[i][j] stores the minimum
// number of cuts required to cut a rectangle of size (i X j) into squares
let dp = new Array(A + 1).fill().map(() => new Array(B + 1).fill(Number.MAX_SAFE_INTEGER));
for (let i = 0; i <= A; i++) {
for (let j = 0; j <= B; j++) {
// If the rectangle is already a square, then 0 cuts are required
if (i === j) {
dp[i][j] = 0;
} else {
// Iterate over all the possible cuts we can make horizontally
for (let k = 1; k < j; k++) {
dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[i][j - k] + 1);
}
// Iterate over all the possible cuts we can make vertically
for (let k = 1; k < i; k++) {
dp[i][j] = Math.min(dp[i][j], dp[k][j] + dp[i - k][j] + 1);
}
}
}
}
// Return the minimum number of cuts required to cut a rectangle of size (A X B) into squares
return dp[A][B];
}
// Sample Input
let A = 3, B = 5;
console.log(solve(A, B));
Time Complexity: O(A * A * B + A * B * B), where A and B are the dimensions of the input rectangle.
Auxiliary Space: O(A * B)
Similar Reads
Cutting Rectangles Given a rectangle of dimensions L x B find the minimum number (N) of identical squares of the maximum side that can be cut out from that rectangle so that no residue remains in the rectangle. Also, find the dimension K of that square. Examples: Input: L = 2, B = 4Output: N = 2, K = 2Explanation: 2 s
4 min read
Minimum squares to cover a rectangle Given a rectangle with length l and breadth b, we need to find the minimum number of squares that can cover the surface of the rectangle, given that each square has a side of length a. It is allowed to cover the surface larger than the rectangle, but the rectangle has to be covered. It is not allowe
9 min read
Minimum squares to evenly cut a rectangle Given a rectangular sheet of length l and width w. we need to divide this sheet into square sheets such that the number of square sheets should be as minimum as possible.Examples: Input :l= 4 w=6 Output :6 We can form squares with side of 1 unit, But the number of squares will be 24, this is not min
4 min read
Total area of two overlapping rectangles Given the coordinates of two rectangles in a 2D plane, the first rectangle is defined by its bottom-left corner (ax1, ay1) and its top-right corner (ax2, ay2) and the second rectangle is defined by its bottom-left corner (bx1, by1) and its top-right corner (bx2, by2). The task is to find the total a
7 min read
Rod Cutting Problem in C The Rod Cutting problem is a classic problem in dynamic programming. Given a rod of length n inches and an array of prices that contains prices of all pieces of size smaller than n, the task is to determine the maximum value obtainable by cutting up the rod and selling the pieces.In this article, we
8 min read