Dadas duas formas contíguas da mesma área, determine a maneira ideal de dividir a primeira forma em um número mínimo de segmentos contíguos, de forma que eles possam ser reorganizados para formar a segunda forma. Em outras palavras, encontre o número mínimo de segmentos necessários que podem formar as duas formas.
"Contíguo" significa que todos os quadrados da forma podem ser alcançados a partir de qualquer outro quadrado andando pelas bordas. Formas e segmentos podem ter furos.
"Reorganizar" significa que você move os segmentos; você pode traduzir, girar e refleti-los.
As formas estão contidas em uma grade; em outras palavras, cada forma consiste em uma coleção de quadrados de unidades unidos por seus cantos / arestas.
Especificações de entrada
A entrada será fornecida em algum formato razoável - lista de pontos, matriz de cadeias representando cada grade, etc. Você também pode obter os tamanhos da grade, se solicitado. As grades terão as mesmas dimensões e as duas formas terão a mesma área e a área será positiva.
Especificações de saída
A saída deve ser apenas um número inteiro positivo único. Observe que sempre haverá uma resposta positiva porque, na pior das hipóteses, você apenas divide as formas em N
unidades de quadrados.
Exemplos
Os exemplos são apresentados como uma grade .
representando um espaço em branco e #
representando parte da forma.
Caso 1
Entrada
.....
.###.
.#.#.
.###.
.....
###..
..#..
..#..
..###
.....
Resultado
2
Explicação
Você pode dividi-lo em dois blocos em forma de L de 4:
#
###
Caso 2
Entrada
#...
##..
.#..
.##.
.##.
####
....
....
Resultado
2
Explicação
Você pode dividir as formas da seguinte maneira:
A...
AA..
.A.
.BB.
.AA.
BBAA
....
....
Você também pode fazer:
A...
AA..
.B..
.BB.
.AB.
AABB
....
....
Caso 3
Entrada
#....#
######
.####.
.####.
Resultado
2
Explicação
A....B
AAABBB
.ABBB.
.AAAB.
(Este caso de teste demonstra a necessidade de girar / refletir formas para obter uma saída ideal)
Caso 4
Entrada
.###.
..#..
.##..
.##..
Resultado
2
Explicação
Não importa como você seleciona blocos, selecionar um 2x1 da primeira forma necessariamente impede que os outros dois sejam agrupados; assim, você pode usar um 2x1 e dois 1x1s. No entanto, (obrigado @Jonah), você pode dividi-lo em uma forma de L de 3 blocos e um único quadrado da seguinte forma:
.AAB.
..A..
.AA..
.BA..
Respostas:
Python 3.6 ,
799791 bytes7 bytes salvos por Jonathan Frech e motavica
Experimente online!
Uso
A(s, t)
assume duas formas em que cada forma é fornecida por uma lista dex, y
posições da grade.Uma função auxiliar para converter a representação gráfica em uma lista de posições está abaixo:
Exemplo:
Explicação
O algoritmo usado aqui é um pouco melhor que a força bruta, armazenando sub-formas em cache. Para uma determinada forma, ele armazena em cache todas as maneiras de dividir essa forma em duas formas contíguas, depois normalizo essas formas (mude as coordenadas para que iniciem na origem e, em seguida, encontre uma rotação / reflexão dela que é usada no cache) e armazene-os no cache para procurar rapidamente mais tarde. Todas as sub-formas têm suas sub-formas em cache também até que elas atinjam a forma de bloco único.
Essas sub-formas são geradas convertendo-a em uma lista de adjacência de gráfico e usando um BFS para gerar todos os sub-gráficos. Podemos então filtrar esses subgráficos para aqueles em que os vértices que não foram incluídos são um componente conectado. Determinar se o gráfico está conectado é feito com outro BFS.
Após a conclusão do cache, a solução é encontrada comparando as duas formas para encontrar as sub-formas que ele tem em comum. Depois de ter essa lista de sub-formas, ele pega o par de sub-formas que sobraram após remover a forma comum e aplica recursivamente o mesmo algoritmo novamente para encontrar o número mínimo de blocos necessários para reconstruir a forma. Isso retorna a sub-forma com o mínimo de todos esses valores e temos a nossa solução.
Eu coloquei uma versão anotada abaixo para explicar o que cada linha está fazendo.
fonte
if s==t else
possivelmente poderia ser revertida, permitindo a substituição de!=
para^
.if i<len(s)-1else
~>if-~i<len(s)else
.def A(s,t):U(s);U(t);return V(P(s),P(t))
possivelmentelambda s,t:U(s)or U(t)or V(P(s),P(t))
, economizando três bytes.s.union(*[g[n]for n in s])
~>s.union(*map(g.get,s))