Um jogo de fechaduras e chaves

12

Existem n caixas, numeradas de 1-n . Cada caixa está bloqueada, de modo que possa ser aberta por apenas um tipo de chave correspondente (também numerado de 1-n ). Essas chaves estão espalhadas aleatoriamente nas caixas (uma caixa pode ter qualquer número de chaves, uma chave pode ter qualquer número de duplicatas) e, em seguida, todas as caixas são fechadas. Um tesouro (com o número 0 ) também foi trancado em muitas das caixas.

Você contratou um serralheiro para recuperar todo o tesouro. Ele cobra por cada caixa que ele abre. Não há nenhum custo para abrir uma caixa para a qual a chave já está disponível.

Entrada é o conteúdo de cada caixa. Você pode decidir o formato da entrada.

Produza o custo mínimo necessário para obter os tesouros.

Notas

  1. Seu algoritmo pode levar um longo tempo, mas isso é irrelevante.
  2. O menor código vence.
  3. Não há necessidade de se preocupar com entrada inválida.

Dados de amostra

Aqui a linha i representa as chaves presentes na caixa i .

Entrada

2 0
3
4 0
5 6 0
6
0

Resultado

1

Entrada

2 0
3 0

4 0
6
5 0

Resultado

3

Entrada

2 4 0
3 0

1 0
6
5 0

Resultado

2

Entrada

1
3 4


2 6
5

Resultado

0
ghosts_in_the_code
fonte
2
Talvez isso esteja relacionado a isso ?
Addison Crump
Também relacionado: puzzling.stackexchange.com/questions/23150/...
Leif Willerts
@VoteToClose Nice video. É semelhante, exceto pelo fato de falar de um quebra-cabeça matemático e de um algoritmo específico, e não de um generalizado.
ghosts_in_the_code
1
Este parece estar relacionada com esse quebra-cabeça sobre 100 caixas trancadas de madeira e aço: puzzling.stackexchange.com/q/17852/4551
XNOR
4
@ghosts_in_the_code Não se trata de simplicidade, mas de flexibilidade. Geralmente, os desafios que requerem entrada estruturada permitem qualquer formato de lista conveniente, desde que os dados não sejam pré-processados. Dependendo do idioma, isso pode significar um arquivo separado por espaço em branco, como você possui, ou pode significar [[1] [3 4] [] [] [2 6] [5]]ou talvez {{1},{3,4},{},{},{2,6},{5}}. Dessa forma, a maioria dos idiomas pode reduzir a leitura da entrada para algo tão trivial quanto i=eval(read())e se concentrar na parte divertida do desafio.
Martin Ender

Respostas:

6

CJam, 59 52 50 49 45 43 42 bytes

qN/ee::~e!{_0+{0a&}#>W%_{1$|(z@-},,\;}%:e<

Obrigado a @ MartinBüttner por jogar fora 3 bytes e abrir caminho para mais 4!

Experimente on-line no intérprete CJam .

Como funciona

qN/      e# Read all input and split it at linefeeds.
ee       e# Enumerate the lines.
         e# STACK: [[0 "i0 i1 ..."] [1 "j0 j1 ..."] ...]
::~      e# Apply ~ (bitwise NOT/evaluate) to each item of the pairs.
         e# STACK: [[-1 i0 i1 ...] [-2 j0 j1 ...] ...]
e!       e# Push all unique permutations of the resulting array.
{        e# For each permutation:
  _0+    e#   Push a copy and append 0 to it.
  {0a&}# e#   Find the first index of an element that contains 0.
  >      e#   Discard all previous elements of the array.
  W%     e#   Reverse the resulting array.
         e#   We now have a (partial) permutation that contains
         e#   all treasures and ends with a treasure.
  _      e#   Push a copy. The original (which contains lists, but no 
              numbers) will serve as accumulator.
  {      e#   Filter; for each list in the array:
    1$|  e#     Push a copy of the accumulator and perform set union.
    (    e#     Shift out the first element (bitwise NOT of 0-based index).
    z    e#     Apply absolute value to push the 1-based index.
    @-   e#     Perform set difference with the former state of the 
         e#     accumulator. This pushes an empty list iff the 1-based
         e#     index was already in the accumulator, i.e., iff we already
         e#     had a key.
  },     e#   Keep the element if we did not have the key.
  ,      e#   Count the kept elements.
  \;     e#   Discard the accumulator from the stack.
}%       e#
:e<      e# Get the minimum of all results.
Dennis
fonte
2
Você poderia adicionar uma explicação para nós sem a compreensão do CJam? : D Gostaria de saber como isso funciona.
Addison Crump
2
@VoteToClose Veja este CJAM101
user41805
array long &obras, para que possa remover a apartir 0a&. Infelizmente, isso torna um pouco mais difícil pegá-lo.
Peter Taylor
@ PeterTaylor Infelizmente, se eu substituir 0a&por 0&, também tenho que substituir 0+por 0aa+, pois 0 0&é falso.
Dennis
@VoteToClose Eu editei minha resposta.
Dennis
2

CJam (53 bytes)

Nq+N/:a::~:A,_m*_.&{,}$_{{_Af=e_|}:PA,*A,,^0-P0&!}#=,

Isso é muito lento para o intérprete online.

Dissecação

Nq+N/:a::~:A      e# Parse the input into arrays and store in A
,_m*_.&           e# Generate (with duplicates) a powerset of [0 1 ... n]
{,}$              e# Sort by size
_{                e# Create a copy and search for first index satisfying...
  {_Af=e_|}:P     e#   Store in P a block which does a reachability expansion
  A,*             e#   Apply it n times (no path can be longer than n)
  A,,^0-          e#   Invert to get the unreached nodes (except 0)
  P               e#   Apply P again to see what's reached from the unreached nodes
  0&!             e#   Check that it doesn't include [0]
}#
=,                e# Look up the powerset element at that index and find length
Peter Taylor
fonte
Eu recebi java.lang.OutOfMemoryError: Java heap spacecom o seu programa.
Zaman
@monmonio, não é particularmente escalável. Eu não o testei com entradas maiores que as entradas de teste da pergunta, por isso não tenho certeza de quão longe ele pode ir em um heap padrão de 1 GB.
Peter Taylor
Eu estava tentando a linha 6 aqui mostrada como uma matriz em JS: é [ [4,0], [1,3,4], [0], [6,0], [3,0], [5]]claro com o estilo de entrada como mostrado no post original.
Zaman
@qumonio, no meu computador ele lida com essa entrada com apenas 128MB de heap, o que é menor do que o padrão.
22415 Peter
0

Haskell, 173 bytes

l é quem você quer ligar.

Não tenho certeza se eu não deveria usar um pseudo- em Mapvez (em [(Int,[Int])]vez de [[Int]]).

l=o[].map(map read).map words.lines
o[]b|0`notElem`concat b=0|0<1=1+minimum[o[n]b|n<-[1..length b],b!!(n-1)/=[]]
o(n:k)b=o(filter(/=0)(k++b!!(n-1)))(take(n-1)b++[]:drop n b)
Leif Willerts
fonte