Игра замков и ключей

12

Есть n ящиков, пронумерованных 1-н . Каждый ящик заблокирован, так что его можно открыть только одним ключом соответствующего типа (также пронумерованным 1-n ). Эти ключи случайным образом разбросаны по блокам (один ящик может иметь любое количество ключей, один ключ может иметь любое количество дубликатов), а затем все ящики закрываются. Сокровище (пронумерованное 0 ) также было заперто во многих коробках.

Вы наняли слесаря, чтобы забрать все сокровища. Он взимает плату за каждую открытую им коробку. За открытие ящика, для которого ключ уже доступен, плата не взимается.

Ввод - это содержимое каждого поля. Вы можете выбрать формат ввода.

Выведите минимальную стоимость, необходимую для получения сокровищ.

Примечания

  1. Ваш алгоритм может занять много времени, но это не имеет значения.
  2. Самый короткий код выигрывает.
  3. Не нужно беспокоиться о неверном вводе.

Образец данных

Здесь строка i представляет ключи, присутствующие в блоке i .

вход

2 0
3
4 0
5 6 0
6
0

Выход

1

вход

2 0
3 0

4 0
6
5 0

Выход

3

вход

2 4 0
3 0

1 0
6
5 0

Выход

2

вход

1
3 4


2 6
5

Выход

0
ghosts_in_the_code
источник
2
Возможно, это связано с этим ?
Эддисон Крамп
Также связано: puzzling.stackexchange.com/questions/23150/…
Лейф Виллертс
@VoteToClose Хорошее видео. Это похоже на то, что речь идет о математической головоломке и конкретном алгоритме, а не об обобщенном.
ghosts_in_the_code
1
Это похоже на головоломку о 100 закрытых коробках из дерева и стали: puzzling.stackexchange.com/q/17852/4551
xnor
4
@ghosts_in_the_code Речь идет не о простоте, а о гибкости. Обычно задачи, требующие структурированного ввода, допускают любой удобный формат списка, если данные не обрабатываются заранее. В зависимости от языка, который может означать разделенный пробелами файл, как у вас, или это может означать [[1] [3 4] [] [] [2 6] [5]]или, может быть {{1},{3,4},{},{},{2,6},{5}}. Таким образом, большинство языков могут уменьшить чтение входных данных до чего-то тривиального i=eval(read())и сосредоточиться на забавной части задачи.
Мартин Эндер

Ответы:

6

CJam, 59 52 50 49 45 43 42 байта

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

Спасибо @ MartinBüttner за то, что он сыграл в гольф 3 байта и проложил путь еще 4!

Попробуйте онлайн в интерпретаторе CJam .

Как это устроено

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.
Деннис
источник
2
Не могли бы вы добавить объяснение для нас без дара понимания CJam? : D Я хотел бы знать, как это работает.
Эддисон Крамп
2
@VoteToClose Посмотрите на этот CJAM101
user41805
array long &работает, так что вы можете удалить aиз 0a&. К сожалению, это делает его немного сложнее поймать вас.
Питер Тейлор
@PeterTaylor К сожалению, если я заменю 0a&с 0&, я также должен заменить 0+с 0aa+, так как 0 0&это falsy.
Деннис
@VoteToClose Я отредактировал свой ответ.
Деннис
2

CJam (53 байта)

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

Это слишком медленно для онлайн-переводчика.

рассечение

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
Питер Тейлор
источник
Я получил java.lang.OutOfMemoryError: Java heap spaceс вашей программой.
MaMan
@qumonio, это не особенно масштабируемо. Я не тестировал его с входными данными, большими, чем тестовые входы в вопросе, поэтому я не уверен, насколько далеко он может пройти в стандартной куче 1 ГБ.
Питер Тейлор
Я пробовал 6 строчку, показанную здесь как массив в JS: [ [4,0], [1,3,4], [0], [6,0], [3,0], [5]]конечно, со стилем ввода, как показано в оригинальном посте.
MaMan
@qumonio, на моем компьютере он обрабатывает этот ввод нормально только с 128 МБ кучи, что меньше, чем по умолчанию.
Питер Тейлор
0

Haskell, 173 байта

l это тот, кого вы хотите позвонить.

Не уверен, стоит ли мне использовать псевдо- Mapвместо ( [(Int,[Int])]вместо [[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)
Лейф Виллертс
источник