Введение
У сборщика налогов есть некоторые проблемы с управлением налогами его королевства: исторические записи сгорели в большом пожаре.
Он хочет выяснить, сколько возможного прошлого может быть с точки зрения того, откуда унаследованы текущие деньги. К счастью, его королевство очень просто.
Королевство может быть смоделировано двумерной логической матрицей, где l
представляет кого-то, кто унаследовал деньги, и O
кого-то, кто не имеет. Например:
l O l l
O O O l
l O l O
O O O l
(Это всегда будет прямоугольник)
В следующем поколении королевство меньше (волки сильны!).
Следующее поколение будет выглядеть так, наложенное на предыдущее поколение ( x
это заполнитель для потомка в следующем поколении)
l O l l
x x x
O O O l
x x x
l O l O
x x x
O O O l
Потомок будет смотреть на предков, которые непосредственно вокруг них (Таким образом, в левом верхнем углу x
будет видеть { l
, O
, O
, O
}, называется Unaligned прямоугольной окрестности )
Если только один предок унаследовал деньги, потомок унаследует деньги от них. Если более чем один предок унаследовал деньги, они ссорятся, и потомок в конечном итоге не наследует деньги. Если никто не унаследовал деньги, потомок не унаследует никаких денег.
(Более одного потомка могут наследовать от одного предка)
Итак, следующее поколение будет выглядеть так:
l l O
l l O
l l O
Вызов
вход
Текущее состояние генерации, как массив массивов любых двух различных значений, где все внутренние массивы имеют одинаковую длину.
Например, для приведенного выше примера это может быть:
[
[True, True, False],
[True, True, False],
[True, True, False]
]
Вывод
Целое число, представляющее количество уникальных предыдущих поколений, где следующее поколение является входным.
Можно предположить, что ответ всегда будет меньше 2 ^ 30 - 1. (или 1073741823).
Предыдущее поколение будет называться «прообразом», и эта задача будет заключаться в подсчете прообразов .
счет
Это быстрый код вызов, поэтому каждая заявка будет проверена на моем компьютере, и заявка, которая займет меньше всего времени, станет победителем.
Пример ввода и вывода
(Где 1
потомок, который унаследовал деньги, и 0
потомок, который не унаследовал деньги)
Входные данные:
[[1, 0, 1],
[0, 1, 0],
[1, 0, 1]]
Вывод:
4
Входные данные:
[[1, 0, 1, 0, 0, 1, 1, 1],
[1, 0, 1, 0, 0, 0, 1, 0],
[1, 1, 1, 0, 0, 0, 1, 0],
[1, 0, 1, 0, 0, 0, 1, 0],
[1, 0, 1, 0, 0, 1, 1, 1]]
Вывод:
254
Входные данные:
[[1, 1, 0, 1, 0, 1, 0, 1, 1, 0],
[1, 1, 0, 0, 0, 0, 1, 1, 1, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0, 1, 1, 0, 0]]
Вывод:
11567
Ответы:
C ++ с использованием библиотеки BuDDy
Это казалось хорошим предлогом для игры с бинарными диаграммами решений . Королевство преобразуется в большую логическую формулу, в которой мы должны подсчитать количество способов, которыми оно может быть удовлетворено. Это может (иногда) быть сделано более эффективно, чем кажется.
Царство должно быть задано как программная константа в виде плоского массива и явно заданных измерений. (Хороший ввод оставлен в качестве упражнения для читателя :-)
Вот неловко простой код:
Чтобы скомпилировать с Debian 8 (Джесси), установите
libbdd-dev
и сделайтеg++ -std=c++11 -o hist hist.cpp -lbdd
. (Оптимизация параметров практически не имеет значения, потому что настоящая работа выполняется в библиотеке.)Большие примеры могут привести к сообщениям о сборке мусора. Их можно подавить, но я предпочитаю их видеть.
bdd_satcount
возвращает adouble
, но этого достаточно для ожидаемого диапазона результатов. Та же техника подсчета возможна с точными (большими) целыми числами.Код оптимизирован для
ROWS<COLS
. Если у вас намного больше строк, чем столбцов, было бы неплохо перенести матрицу.источник
Python 2.7
Это просто наивная первая попытка. Это не особенно быстро, но это правильно.
Первое наблюдение заключается в том, что каждая ячейка зависит ровно от четырех ячеек предыдущего поколения. Мы можем представить эти четыре ячейки как 4-битное число (0-15). Согласно правилам, если ровно одна соседняя ячейка в предыдущем поколении есть
1
, то данная ячейка в текущем поколении будет1
, иначе будет0
. Те соответствуют полномочиям двух, а именно[1, 2, 4, 8]
. Когда четыре предка представлены в виде 4-битного числа, любое другое число приведет к появлению0
в текущем поколении. С помощью этой информации, увидев ячейку в текущем поколении, мы можем сузить возможности соседства в предыдущем поколении до одной из четырех или одной из двенадцати возможностей соответственно.Я решил представить окрестности следующим образом:
где 0 - младший бит и т. д.
Второе наблюдение состоит в том, что для двух соседних ячеек в текущем поколении два соседства из предыдущего поколения перекрываются:
или:
В горизонтальном случае
2
соседство слева пересекается с3
соседством справа, а также0
слева и1
справа. В вертикальном случае область1
сверху сверху перекрывается с областью3
снизу, а также0
сверху и2
снизу.Это совпадение означает, что мы можем сузить возможности для еще не выбранных районов на основе того, что мы уже выбрали. Код работает слева направо, сверху вниз, в рекурсивном поиске возможных глубин вначале глубины. Следующая диаграмма показывает, какие предыдущие окрестности мы должны учитывать при рассмотрении возможных окрестностей текущей ячейки:
Вот код:
Чтобы запустить это:
источник
O(<something>^n)