SoulMate Roulette
O mundo precisa da tua ajuda.
Descobertas científicas recentes provam que cada pessoa tem uma única
alma gémea: alguém escolhido ao acaso, algures no mundo, à nascença. Não
sabes quem é nem onde está, mas, como no cliché romântico,
reconhecer-se-ão assim que os vossos olhos se cruzarem.
Felizmente, as mesmas descobertas mostram que a tua alma gémea vive
na mesma época que tu e tem uma idade próxima da tua — uma condição
ainda mais restritiva do que a fórmula
habitual para a diferença de idades.
Mesmo com esta restrição, a maioria de nós tem cerca de quinhentos
milhões de candidatos possíveis. Esquece o género, a orientação sexual,
a cultura ou a língua: cada pessoa só tem uma orientação, para a sua
alma gémea. As probabilidades de a encontrar são minúsculas.
Uma pessoa em dez mil encontra a sua alma
gémea.
Perante a ameaça de morrer sozinho, a sociedade precisa de se
reorganizar para tornar possível o maior número de encontros de
olhares.
Poderíamos construir enormes tapetes rolantes para fazer passar filas
de pessoas umas pelas outras…
Duas filas de pessoas cruzam-se em
tapetes rolantes.
Ou poderíamos usar câmaras de vídeo…
Duas pessoas ponderam um encontro através
de uma câmara.
Se todos usassem um sistema como o Chatroulette durante oito horas
por dia, sete dias por semana, e bastassem alguns segundos para
reconhecer a pessoa certa, seria teoricamente possível encontrar todas
as almas gémeas em algumas décadas.
Mas muitas pessoas mal conseguem arranjar tempo para o romance,
quanto mais dedicar-lhe vinte anos. Talvez só os mais ricos pudessem
passar o dia no SoulMateRoulette. Infelizmente para esse 1%, a maioria
das suas almas gémeas encontra-se nos outros 99%. Se apenas 1% da
população usar o serviço, só 1% desse grupo encontrará a sua
cara-metade: uma pessoa em dez mil.
«Acaso é uma palavra vazia de sentido; nada pode existir sem uma
causa.»
Voltaire, Dictionnaire philosophique (1764).
Para encontrar uma solução viável, todos os países decidiram apostar
em ti, uma pessoa competente em informática, para escrever um programa
que analise fotografias dos olhos da população.
As pessoas estão impacientes. Profissões como operador de caixa já se
tornaram as mais procuradas pelo seu potencial de contacto visual! Nos
próximos dias vais receber cartões de memória, à medida que as câmaras
ficam sem espaço. Os analistas do governo irão reunir estas análises
parciais para decidir as correspondências finais. Essa decisão não é
tua: a especificação da tua tarefa vem a seguir.
A tua tarefa
Para cada cartão de memória, apresenta a compatibilidade de
todos os pares não ordenados de cidadãos. O resultado é
uma lista ordenada de pares, não uma atribuição final de almas
gémeas.
Entrada
A entrada padrão contém exatamente 532126 bytes:
1337 ficheiros BMP consecutivos de 398 bytes cada, sem separadores,
contagem inicial ou bytes adicionais. Os identificadores dos cidadãos
vão de 0 a 1336, pela ordem de entrada.
| Assinatura; tamanho do ficheiro |
BM; 398 bytes |
| Cabeçalho do ficheiro; cabeçalho DIB |
14 bytes; BITMAPINFOHEADER de 40 bytes |
| Largura; altura |
42; 42 píxeis, linhas de baixo para cima |
| Planos; bits por píxel |
1; 1 |
| Compressão; início dos píxeis |
0; deslocamento de 62 bytes |
| Paleta |
Preto primeiro, branco depois; duas entradas de 4 bytes |
| Linhas de píxeis |
42 linhas de 8 bytes, incluindo o preenchimento |
Cada píxel branco representa um ponto do contorno do olho; o preto é
o fundo. As coordenadas dos centros dos píxeis variam entre 0 e 41 em
cada eixo. Cada imagem tem de conter pelo menos três pontos brancos não
colineares. Existe um olho por cidadão e todos os olhos de um conjunto
são do mesmo lado. As imagens já contêm os contornos.
Compatibilidade
A forma que representa cada olho é o conjunto de vértices do
invólucro convexo dos seus pontos brancos. Os pontos colineares
no interior de uma aresta não são vértices. As distâncias referem-se a
estes vértices, não ao interior dos polígonos nem aos segmentos
contínuos das arestas.
Para os conjuntos de vértices A e B,
definem-se:
h(A,B) = máximo, para a em A, do mínimo de ||a-b|| para b em B
H(A,B) = max(h(A,B), h(B,A))
score(A,B) = 100 * (1 - H(A,B) / sqrt(42*42 + 42*42))
||a-b|| é a distância euclidiana. O denominador definido
pelo problema é sqrt(3528).
Saída
Para uma entrada válida, escreve 893116 linhas, uma
por par a < b:
a - b: score%
Os pares surgem por ordem decrescente de compatibilidade, antes de
qualquer arredondamento. Em caso de igualdade, ordenam-se por
a crescente e depois por b crescente. A
percentagem usa ponto decimal e exatamente duas casas decimais,
arredondadas à centésima mais próxima; nos empates positivos, arredonda
para cima. Os identificadores não têm zeros à esquerda. Cada linha
termina em LF.
Se o tamanho da entrada, algum BMP ou alguma forma forem inválidos,
escreve apenas estas linhas literais em inglês:
And if it wasn't for you, baby,
I really think that I would
have somebody else.
Limites
Tempo: 21 segundos. Memória: 550
MB.
Exemplo de entrada e saída
Descarregar a entrada binária e a saída
esperada. O arquivo contém example_input.raw e
example_output.txt; a entrada binária não é apresentada
como texto.
Créditos
História e ilustrações inspiradas em «Soul Mates», What If?, de
Randall Munroe. A mensagem de entrada inválida cita If I Didn’t Have
You, de Tim Minchin.
Diogo Peralta Cordeiro · Programação Competitiva (CC3036) · DCC/FCUP
· 2021