Ao pensar em um problema, percebi que precisava criar um algoritmo eficiente para resolver a seguinte tarefa:
O problema: recebemos uma caixa quadrada bidimensional do lado cujos lados são paralelos aos eixos. Podemos examiná-lo através do topo. No entanto, também existem segmentos horizontais. Cada segmento tem um inteiro coordenada x ( ) e -coordena ( ) e pontos Connects e (veja o imagem abaixo).
Gostaríamos de saber, para cada segmento de unidade na parte superior da caixa, quão profundo podemos olhar verticalmente dentro da caixa se examinarmos esse segmento.
Exemplo: dados e segmentos localizados como na figura abaixo, o resultado é . Veja como a luz profunda pode entrar na caixa.
Felizmente para nós, tanto e são bastante pequeno e podemos fazer os cálculos off-line.
O algoritmo mais fácil de resolver esse problema é a força bruta: para cada segmento, percorra toda a matriz e atualize-a sempre que necessário. No entanto, isso nos dá um não muito impressionante .
Uma grande melhoria é usar uma árvore de segmentos capaz de maximizar valores no segmento durante a consulta e ler os valores finais. Não vou descrevê-lo mais, mas vemos que a complexidade do tempo é .
No entanto, criei um algoritmo mais rápido:
Esboço:
Classifique os segmentos em ordem decrescente de coordenada (tempo linear usando uma variação da classificação de contagem). Agora observe que, se qualquer segmento de unidade já foi coberto por qualquer segmento antes, nenhum segmento a seguir poderá limitar o feixe de luz que passa por esse segmento de unidade . Em seguida, faremos uma varredura de linha de cima para baixo na caixa.x x
Agora, vamos introduzir algumas definições: o segmento da unidade é um segmento horizontal imaginário na varredura cujos coordenadas são números inteiros e cujo comprimento é 1. Cada segmento durante o processo de varredura pode ser desmarcado (ou seja, um feixe de luz saindo do o topo da caixa pode alcançar esse segmento) ou marcado (caso oposto). Considere um segmento de unidade com , sempre desmarcado. Vamos também introduzir os conjuntos . Cada conjunto conterá uma sequência inteira de segmentos de unidades marcados consecutivos (se houver algum) com a seguinte marca não marcadax x x 1 = n x 2 = n + 1 S 0 = { 0 } , S 1 = { 1 } , … , S n = { n } x segmento.
Precisamos de uma estrutura de dados capaz de operar nesses segmentos e conjuntos com eficiência. Usaremos uma estrutura de união de busca estendida por um campo que contém o índice máximo do segmento de unidades (índice do segmento não marcado ).
Agora podemos lidar com os segmentos com eficiência. Digamos que agora estamos considerando o ésimo segmento em ordem (chame de "consulta"), que começa em e termina em . Precisamos encontrar todos os segmentos não marcados da unidade que estão contidos no ésimo segmento (esses são exatamente os segmentos nos quais o feixe de luz terminará). Vamos fazer o seguinte: primeiro, encontramos o primeiro segmento não marcado dentro da consulta ( encontre o representante do conjunto no qual está contido e obtenha o índice máximo desse conjunto, que é o segmento não marcado por definição ). Então este índicex 1 x 2 x i x 1 x y x x + 1 x ≥ está dentro da consulta, adicioná-lo para o resultado (o resultado para este segmento é ) e marcar este índice ( União conjuntos contendo e ). Em seguida, repita esse procedimento até encontrarmos todos os segmentos não marcados , ou seja, a próxima consulta Find nos fornece o índice .
Observe que cada operação de união de localização será realizada em apenas dois casos: ou começamos a considerar um segmento (que pode acontecer vezes) ou apenas marcamos um segmento de unidade (isso pode acontecer vezes). Assim, a complexidade geral é ( é uma função inversa de Ackermann ). Se algo não estiver claro, posso elaborar mais sobre isso. Talvez eu possa adicionar algumas fotos se tiver algum tempo.x n O ( ( n + m ) α ( n ) ) α
Agora cheguei ao "muro". Não consigo criar um algoritmo linear, embora pareça que deveria haver um. Então, eu tenho duas perguntas:
- Existe um algoritmo de tempo linear (ou seja, ) resolvendo o problema de visibilidade do segmento horizontal?
- Caso contrário, qual é a prova de que o problema de visibilidade é ?