Three Logos
Implementación
Podemos probar por fuerza bruta todas las rotaciones de los tres rectángulos con una máscara de bits de , donde el bit indica si el -ésimo rectángulo debe rotarse grados. El resto es comprobar si las configuraciones son válidas.
Complejidad temporal: , donde es el número de rectángulos (en este caso, 3) y es la longitud del lado del cuadrado.
#include <bits/stdc++.h>
using namespace std;
const int N = 3;
int main() {
vector<pair<int, int>> logos(N);
for (int i = 0; i < N; i++) { scanf("%d%d", &logos[i].first, &logos[i].second); }
long long area = 0;
for (pair<int, int> p : logos) { area += p.first * p.second; }
// Si el área no es un cuadrado perfecto, ya es inválido
int len = 1;
while (len * len < area) { len++; }
if (len * len != area) {
printf("-1");
return 0;
}
// Recorremos todas las rotaciones de cada rectángulo
for (int rotate_mask = 0; rotate_mask < (1 << N); rotate_mask++) {
vector<string> grid(len, string(len, 'Z')); // Grilla temporal
// 'Z' representa un espacio vacío en la grilla
int num_placed = 0;
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
if (grid[i][j] == 'Z') {
if (num_placed == N) {
// Ya hemos colocado todos los logos
goto outer;
}
int w = logos[num_placed].first;
int h = logos[num_placed].second;
if (rotate_mask & (1 << num_placed)) {
// Rotamos 90 grados
swap(w, h);
}
// Colocamos la configuración
for (int r = i; r < i + h; r++) {
for (int c = j; c < j + w; c++) {
if (r >= len || c >= len || grid[r][c] != 'Z') {
// Fuera de límites o ya hay un logo aquí
goto outer;
}
grid[r][c] = num_placed + 'A';
}
}
num_placed++;
}
}
}
// En este punto, todos los logos deben estar colocados
assert(num_placed == N);
printf("%d\n", len);
for (int i = 0; i < len; i++) { printf("%s\n", grid[i].c_str()); }
return 0;
// Continuamos la iteración
outer:;
}
printf("-1");
}import java.util.*;
public class ThreeLogos {
private static final int N = 3;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[][] logos = new int[N][2];
for (int i = 0; i < N; i++) {
logos[i][0] = scanner.nextInt();
logos[i][1] = scanner.nextInt();
}
long area = 0;
for (int[] p : logos) { area += p[0] * p[1]; }
// Si el área no es un cuadrado perfecto, ya es inválido
int len = 1;
while (len * len < area) { len++; }
if (len * len != area) {
System.out.println("-1");
return;
}
// Recorremos todas las rotaciones de cada rectángulo
for (int rotateMask = 0; rotateMask < (1 << N); rotateMask++) {
char[][] grid = new char[len][len];
for (int i = 0; i < len; i++) {
// 'Z' representa un espacio vacío en la grilla
Arrays.fill(grid[i], 'Z');
}
int numPlaced = 0;
outerLoop:
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
if (grid[i][j] == 'Z') {
if (numPlaced == N) {
// Ya hemos colocado todos los logos
break outerLoop;
}
int w = logos[numPlaced][0];
int h = logos[numPlaced][1];
if ((rotateMask & (1 << numPlaced)) != 0) {
// Rotamos 90 grados
int temp = w;
w = h;
h = temp;
}
// Colocamos la configuración
for (int r = i; r < i + h; r++) {
for (int c = j; c < j + w; c++) {
if (r >= len || c >= len || grid[r][c] != 'Z') {
// Fuera de límites o ya hay un logo aquí
continue outerLoop;
}
grid[r][c] = (char)(numPlaced + 'A');
}
}
numPlaced++;
}
}
}
// En este punto, todos los logos deben estar colocados
if (numPlaced == N) {
System.out.println(len);
for (int i = 0; i < len; i++) {
System.out.println(new String(grid[i]));
}
return;
}
}
System.out.println("-1");
}
}def main():
import sys
data = sys.stdin.read().split()
N = 3
logos = [(int(data[i * 2]), int(data[i * 2 + 1])) for i in range(N)]
area = sum(p[0] * p[1] for p in logos)
# Si el área no es un cuadrado perfecto, ya es inválido
len_side = 1
while len_side * len_side < area:
len_side += 1
if len_side * len_side != area:
print("-1")
return
# Recorremos todas las rotaciones de cada rectángulo
for rotate_mask in range(1 << N):
grid = [
["Z" for _ in range(len_side)] for _ in range(len_side)
] # Grilla temporal
# 'Z' representa un espacio vacío en la grilla
num_placed = 0
for i in range(len_side):
for j in range(len_side):
if grid[i][j] == "Z":
if num_placed == N:
# Ya hemos colocado todos los logos
goto_outer = True
break
w, h = logos[num_placed]
if rotate_mask & (1 << num_placed):
# Rotamos 90 grados
w, h = h, w
# Colocamos la configuración
if all(
0 <= r < len_side and 0 <= c < len_side and grid[r][c] == "Z"
for r in range(i, i + h)
for c in range(j, j + w)
):
for r in range(i, i + h):
for c in range(j, j + w):
grid[r][c] = chr(num_placed + ord("A"))
num_placed += 1
else:
goto_outer = True
break
else:
continue
break
else:
# En este punto, todos los logos deben estar colocados
assert num_placed == N
print(len_side)
for row in grid:
print("".join(row))
return
print("-1")
if __name__ == "__main__":
main()Implementación alternativa
Este problema se puede resolver en tiempo (ignorando el tiempo de imprimir la salida), simplemente considerando los dos casos posibles.
Si los logos caben, o bien:
- se colocan uno debajo del otro, similar al primer ejemplo
- o uno se coloca arriba y los otros dos se colocan uno al lado del otro.
#include <bits/stdc++.h>
using namespace std;
struct point {
int x, y;
char ch;
void print(void) {
for (int i = 0; i < this->y; i++) {
for (int j = 0; j < this->x; j++) cout << this->ch;
cout << '\n';
}
}
};
void solve(void) {
point a, b, c;
cin >> a.x >> a.y >> b.x >> b.y >> c.x >> c.y;
a.ch = 'A';
b.ch = 'B';
c.ch = 'C';
// Rotamos los logos para reducir la cantidad de análisis por casos
// Lado más largo = x, lado más corto = y
if (a.x < a.y) swap(a.x, a.y);
if (b.x < b.y) swap(b.x, b.y);
if (c.x < c.y) swap(c.x, c.y);
// Primer caso: los 3 tienen el mismo ancho, así que intentamos colocarlos uno debajo del otro
if (a.x == b.x && a.x == c.x) {
if (a.y + b.y + c.y == a.x) { // Si realmente forman un cuadrado
cout << a.x << "\n";
a.print();
b.print();
c.print();
} else {
cout << "-1\n";
}
return;
}
// Sea a el logo con el mayor x
if (c.x > b.x) swap(b, c);
if (b.x > a.x) swap(a, b);
int remaining_y = a.x - a.y;
// Los rotamos según haga falta
if (b.x == remaining_y) swap(b.x, b.y);
if (c.x == remaining_y) swap(c.x, c.y);
if (b.x + c.x == a.x && c.y == remaining_y && b.y == remaining_y) {
cout << a.x << "\n";
a.print();
for (int i = 0; i < b.y; i++) {
for (int j = 0; j < b.x; j++) cout << b.ch;
for (int j = 0; j < c.x; j++) cout << c.ch;
cout << '\n';
}
return;
}
cout << "-1\n";
}
int main(void) {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
solve();
return 0;
}class Logo:
def __init__(self, x, y, ch):
# Rotamos los logos para reducir la cantidad de análisis por casos
# Lado más largo = x, lado más corto = y
if x < y:
y, x = x, y
self.x = x
self.y = y
self.ch = ch
def rotate(self):
# Rotamos el rectángulo 90 grados
self.x, self.y = self.y, self.x
def print_rectangle(self):
for _ in range(self.y):
print(self.ch * self.x)
def main():
values = [int(i) for i in input().split()]
a = Logo(values[0], values[1], "A")
b = Logo(values[2], values[3], "B")
c = Logo(values[4], values[5], "C")
# Primer caso: los 3 tienen el mismo ancho, así que intentamos colocarlos uno debajo del otro
if a.x == b.x == c.x:
if a.y + b.y + c.y == a.x: # Si realmente forman un cuadrado
print(a.x)
a.print_rectangle()
b.print_rectangle()
c.print_rectangle()
return
# Sea a el logo con el mayor x
if c.x > b.x:
b, c = c, b
if b.x > a.x:
a, b = b, a
remaining_y = a.x - a.y
# Rotamos los rectángulos si su lado más largo, x, coincide con la altura restante
if b.x == remaining_y:
b.rotate()
if c.x == remaining_y:
c.rotate()
if b.y == remaining_y and c.y == remaining_y:
print(a.x)
a.print_rectangle()
for _ in range(b.y):
print(b.ch * b.x + c.ch * c.x)
return
print(-1)
if __name__ == "__main__":
main()