Skip to Content

Three Logos

Editorial oficial 

Implementación

Podemos probar por fuerza bruta todas las rotaciones de los tres rectángulos con una máscara de bits de 232^3, donde el bit ii indica si el ii-ésimo rectángulo debe rotarse 9090 grados. El resto es comprobar si las configuraciones son válidas.

Complejidad temporal: O(2nside2)\mathcal{O}(2^n \cdot \textbf{side}^2), donde nn es el número de rectángulos (en este caso, 3) y side\textbf{side} 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 O(1)\mathcal{O}(1) (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()