Escreva uma função / sub-rotina para classificar uma lista de números inteiros, estilo Tower of Hanoi .
Você receberá uma pilha de números inteiros. Esta é a pilha principal.
Você também recebe mais duas pilhas auxiliares. Porém, essas pilhas auxiliares têm uma propriedade exclusiva: cada elemento deve ser menor ou do mesmo tamanho que o elemento abaixo dele. A pilha principal não tem essa restrição.
Você tem a tarefa de classificar a pilha principal no lugar, colocando os maiores números inteiros por baixo. Sua função / sub-rotina retornará (ou equivalente) o número de movimentos realizados na classificação da pilha.
Nota: você deve classificar a pilha principal no lugar , sem classificar em outra pilha e chamar isso de resposta. No entanto, se por algum motivo não puder fazê-lo, você pode simular as pilhas mutáveis, mas lembre-se de que esse é o tipo da Torre de Hanói; existem apenas 3 pinos e apenas 1 pode ser desordenado.
Sua função / sub-rotina pode inspecionar qualquer pilha a qualquer momento, mas só pode fazer um movimento ao estourar e empurrar. Um único movimento é um pop de uma pilha que é empurrada para outra.
Teste sua função / sub-rotina para cada permutação dos 6 primeiros números naturais. Em outras palavras, teste sua função / sub-rotina {1},{2},...,{6},{1,1},{1,2},...,{1,6},{2,1},...
(deve ser um total de ou possibilidades (obrigado a Howard por corrigir minha matemática)). A função / sub-rotina que move elementos pelo menor número de vezes ganha.61+62+...+66
55986
fonte
6**1+6**2+...+6**6=55986
elementos.Respostas:
Java - solução ideal (1080544 movimentos)
Esta solução cria uma árvore de caminho mais curto a partir do destino e para trás e, em seguida, percorre o caminho do estado inicial para o destino. Muito espaço para melhorar a velocidade, mas ainda completa todos os 55986 problemas em cerca de um minuto.
Assumindo que o algoritmo foi implementado corretamente, essa deve ser a melhor solução teoricamente.
fonte
C - 2547172 para 55986 entradas
Há muito espaço para melhorias aqui. Para minha própria sanidade, simplifiquei isso para que só fosse possível inspecionar o elemento superior de cada pilha. O levantamento dessa restrição autoimposta permitiria otimizações, como determinar a ordem final antecipadamente e tentar minimizar o número de movimentos necessários para alcançá-la. Um exemplo atraente é que minha implementação tem um comportamento de pior caso se a pilha principal já estiver classificada.
Algoritmo:
Análise:
fonte
Python,
39838383912258 move sobre 55986 entradasIsso é muito ineficiente.
Acrescentarei o número total de movimentos após o OP esclarecer se são para todos esses casos ou para outros casos específicos.
Explicação
O que, comentários não são bons o suficiente para você?
Nota para OP: Obrigado por não fazer este código-golfe.
fonte
[2,1,1]
existe uma maneira de obter[2,1,1].index(1)
2, ou seja, a partir do final superior?[2,1,1,3,5].index(1)==2
vez de1
list.index(data)
retorna o índice do itemdata
emlist
. Eu não sei o índice dedata
ie1
len(list)-(list[::-1].index(1))
Python:
1.688.2931.579.1821.524.0541.450.8421.093.195 movimentosO método principal é
main_to_help_best
mover alguns elementos selecionados da pilha principal para a pilha auxiliar. Ele possui um sinalizadoreverything
que define se queremos mover tudo para o especificadodestination
ou se queremos manter apenas o maiordestination
enquanto o restante no outro auxiliar.Supondo que estamos
dst
usando o helperhelper
, a função pode ser descrita a seguir:helper
recursivamentedst
helper
para a principaldst
everything
estiver definido, mova recursivamente os elementos em main paradst
b. Caso contrário, mova recursivamente os elementos principais para
helper
O algoritmo de classificação principal (
sort2
no meu código) irá chamarmain_to_help_best
comeverything
set paraFalse
e, em seguida, moverá o elemento maior de volta para main, depois moverá tudo do auxiliar de volta para main, mantendo-o classificado.Mais explicações incorporadas como comentários no código.
Basicamente, os princípios que eu usei são:
O princípio 3 é implementado não contando a movimentação se a origem for o destino anterior (ou seja, nós apenas mudamos main para help1, então queremos passar de help1 para help2) e, além disso, reduzimos o número de movimentos em 1 se estão movendo-o de volta à posição original (ou seja, principal para ajudar1 e depois ajudar1 para principal). Além disso, se os
n
movimentos anteriores estiverem todos movendo o mesmo número inteiro, podemos reordenar osn
. Portanto, também aproveitamos isso para reduzir ainda mais o número de movimentos.Isso é válido, pois conhecemos todos os elementos da pilha principal; portanto, isso pode ser interpretado como se você visse no futuro que vamos mover o elemento de volta, não devemos fazer isso.
Amostra de execução (as pilhas são exibidas de baixo para cima - portanto, o primeiro elemento é o fundo):
Podemos ver que o pior caso é quando o maior elemento é colocado na segunda parte inferior, enquanto o restante é classificado. Do pior caso, podemos ver que o algoritmo é O (n ^ 2).
O número de movimentos é obviamente mínimo para
n=1
e,n=2
como podemos ver no resultado, e acredito que isso também seja mínimo para valores maiores den
, embora eu não possa provar isso.Mais explicações estão no código.
fonte
4
. O que é isso armazenando o segundo maior elemento no segundo auxiliar? O que isso significa?Java -
21290902083142 move-se em 55986 matrizesO link ideone .
A estrutura para garantir que o algoritmo esteja correto:
O algoritmo real:
A caixa de teste:
fonte
C / C ++ não mediu movimentos (pegs: p1, p2, p3) Não sabe como adicionar código C ++ que usa STL (problema de formatação). Perder partes do código devido aos formatos de tag html no código.
Mesclar dados de movimentação (n + m) em p2 e p3 para p1.
fonte
hanoi(...)
função. Além disso, você tem 2#include
s que não compilam. Por favor, poste o código completo.