Eu tenho um conjunto de pares. Cada par tem a forma (x, y) tal que x, y pertencem a números inteiros do intervalo [0,n)
.
Portanto, se n é 4, tenho os seguintes pares:
(0,1) (0,2) (0,3)
(1,2) (1,3)
(2,3)
Eu já tenho os pares. Agora, eu tenho que construir uma combinação usando n/2
pares de forma que nenhum dos números inteiros seja repetido (em outras palavras, cada número inteiro aparece pelo menos uma vez na combinação final). A seguir estão os exemplos de uma combinação correta e incorreta para melhor entendimento
1. (0,1)(1,2) [Invalid as 3 does not occur anywhere]
2. (0,2)(1,3) [Correct]
3. (1,3)(0,2) [Same as 2]
Alguém pode me sugerir uma maneira de gerar todas as combinações possíveis, uma vez que tenho os pares.
algorithms
graphics
data-structures
computational-geometry
operating-systems
process-scheduling
algorithms
sorting
database-theory
relational-algebra
finite-model-theory
logic
automata
linear-temporal-logic
buchi-automata
complexity-theory
np-complete
decision-problem
machine-learning
algorithms
pattern-recognition
logic
formal-languages
formal-grammars
context-free
Ankit
fonte
fonte
Respostas:
Uma maneira direta é um procedimento recursivo que faz o seguinte em cada chamada. A entrada para o procedimento é uma lista de pares que já foram escolhidos e uma lista de todos os pares.
A maneira de visualizar esse algoritmo é com uma árvore cujos caminhos são sequências de pares não sobrepostos. O primeiro nível da árvore contém todos os pares que contêm 0. No exemplo acima, a árvore é
Neste exemplo, todos os caminhos na árvore realmente fornecem coleções corretas, mas, por exemplo, se deixássemos de fora o par (1,2), o caminho mais à direita teria apenas um nó e corresponderia à falha na etapa 3 da pesquisa.
Algoritmos de pesquisa desse tipo podem ser desenvolvidos para muitos problemas semelhantes de enumerar todos os objetos de um tipo específico.
Foi sugerido que talvez o OP significasse que todos os pares estão na entrada, não apenas um conjunto deles, como diz a pergunta. Nesse caso, o algoritmo é muito mais fácil, porque não é mais necessário verificar quais pares são permitidos. Nem é necessário gerar o conjunto de todos os pares; o pseudocódigo a seguir fará o que o OP pediu. Aqui é o número de entrada, "lista" começa como uma lista vazia e "coberto" é uma matriz de comprimento n inicializada como 0. Poderia ser um pouco mais eficiente, mas esse não é meu objetivo imediato.n n
fonte
Você pode resolvê-lo iterativamente. Suponha que você tenha todas as soluções para o intervalo [ 0 , n ) . Então você pode construir facilmente as soluções S n + 2 a partir de S n . O tamanho aumenta extremamente rapidamente com n , portanto, pode ser bom escrever um gerador em vez de manter todos os conjuntos na memória, veja o exemplo do Python abaixo.Sn [ 0 , n ) Sn + 2 Sn n
Você pode listar todos os pares chamando
fonte
Atualização : minha resposta anterior tratava de gráficos bipartidos, sobre os quais o OP NÃO estava perguntando. Estou deixando por enquanto, como informações relacionadas. mas as informações mais pertinentes estão relacionadas a combinações perfeitas em gráficos não bipartidos.
Nesse sentido, há uma boa pesquisa da Propp que descreve o progresso (até 1999). Algumas das idéias contidas neste artigo e os links relacionados podem ser úteis. o TL; DR é - é complicado :)
--- Início da resposta antiga
Observe que o que você está pedindo para fazer é enumerar todas as combinações perfeitas possíveis em um gráfico bipartido. Existem muitos algoritmos diferentes para fazer isso, e um dos mais recentes é o ISAAC 2001 .
A idéia básica é encontrar uma correspondência perfeita usando fluxos de rede e modificá-la repetidamente usando ciclos alternados (consulte qualquer capítulo do livro de algoritmos sobre fluxos de rede para obter mais informações).
fonte
Cada par que você escolhe elimina duas linhas das quais você não pode mais escolher. Esta ideia pode ser usada para configurar um algoritmo recursivo (no Scala):
Isso certamente pode ser expresso de uma maneira mais eficiente. Em particular, a idéia de não ter que considerar linhas inteiras para combinações não é usada pela chamada para
filter
.fonte
Embora já existam muitas respostas encantadoras para a pergunta, acho que seria bom ressaltar o truque básico e geral por trás delas.
É muito mais fácil gerar combinações exclusivas se você puder ter uma ordem total dos elementos a serem combinados . Dessa forma, a exclusividade é garantida se permitirmos apenas combinações ordenadas. Também não é difícil gerar as combinações classificadas - basta fazer a pesquisa de enumeração de força bruta usual, mas em cada etapa escolha apenas elementos maiores que os já selecionados em cada etapa.
A complicação extra nesse problema específico é o desejo de obter apenas as combinações de comprimento n / 2 (o comprimento máximo). Isso não é difícil de fazer se decidirmos uma boa estratégia de classificação. Por exemplo, como apontado na resposta de Carl Mummet, se considerarmos um tipo lexicográfico (de cima para baixo, esquerda e direita no diagrama da pergunta), derivamos a estratégia de sempre pegar o próximo elemento para que seu primeiro dígito seja o menor número ainda não utilizado.
Também podemos estender essa estratégia se queremos gerar sequências de outros comprimentos. Lembre-se de que sempre que escolhemos um próximo elemento cujo primeiro número não é o menor disponível, excluímos que uma ou mais linhas de elementos apareçam na subsequência classificada, portanto o comprimento máximo da pré-comutação diminui de acordo.
fonte
fonte