CSES Solutions Rectangle Cutting (original) (raw)
Last Updated : 8 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 > dp(A + 1, vector(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)