Эта проблема
Определения
- Определим натуральное число
N
как записываемое число (WN) для набора чисел в системе счисленияM
, если оно может быть записано в этой системе счисления из членовU
используя каждый член не более одного раза. Более строгое определение "записано": - здесьCONCAT
означает конкатенацию. - Определим натуральное число
N
как непрерывное достижимое число (CAN) для набора символов в системе счисленияM
если оно является номером WN дляU
иM
а такжеN-1
является номером CAN дляU
иM
( Другим определением может бытьN
является CAN дляU
иM
если все0.. N
чисел являются WN дляU
иM
). Более строгий:
вопрос
Пусть у нас есть набор из S
натуральных чисел: (мы рассматриваем ноль как натуральное число) и натуральное число M
, M>1
. Проблема состоит в том, чтобы найти максимальное значение CAN (MCAN) для данных U
и M
Данный набор U
может содержать дубликаты - но каждый дубликат не может использоваться более одного раза по причине (т.е. Если U
содержит {x, y, y, z}), то каждый y
может использоваться 0 или 1 раз, поэтому y
может быть используется в 0..2 раза). Также ожидается, что U
будет действительным в системе M
-numeral (то есть не может содержать символы 8
или 9
ни в одном элементе, если M=8
). И, конечно же, члены U
являются числами, а не символами для M
(так что 11
действительна для M=10
) - иначе проблема будет тривиальной.
Мой подход
Сейчас я имею в виду простой алгоритм, который просто проверяет, является ли текущее число CAN через:
- Проверьте, является ли
0
WN для данныхU
иM
? Перейти к 2: мы сделали, MCAN является нулевым - Проверьте, является ли
1
WN для данныхU
иM
? Перейти к 3: мы сделали, MCAN0
- ...
Итак, этот алгоритм пытается построить всю эту последовательность. Я сомневаюсь, что эта часть может быть улучшена, но может быть, это может? Теперь, как проверить, является ли число WN. Это также своего рода "замена грубой силой". Я понимаю, что для M=10
(на самом деле, поскольку мы имеем дело со строками, любой другой M
не проблема) с функцией PHP:
//$mNumber is our N, $rgNumbers is our U
function isWriteable($mNumber, $rgNumbers)
{
if(in_array((string)$mNumber, $rgNumbers=array_map('strval', $rgNumbers), true))
{
return true;
}
for($i=1; $i<=strlen((string)$mNumber); $i++)
{
foreach($rgKeys = array_keys(array_filter($rgNumbers, function($sX) use ($mNumber, $i)
{
return $sX==substr((string)$mNumber, 0, $i);
})) as $iKey)
{
$rgTemp = $rgNumbers;
unset($rgTemp[$iKey]);
if(isWriteable(substr((string)$mNumber, $i), $rgTemp))
{
return true;
}
}
}
return false;
}
-so мы пробуем одну часть, а затем проверяем, может ли остальная часть быть записана с помощью рекурсии. Если это не может быть написано, мы пытаемся следующий член U
Я думаю, что этот момент можно улучшить.
конкретика
Как видите, алгоритм пытается построить все числа до N
и проверить, являются ли они WN. Но единственный вопрос - найти MCAN, поэтому вопрос таков:
- Может быть, конструктивный алгоритм здесь чрезмерен? И, если да, какие еще варианты можно использовать?
- Есть ли более быстрый способ определить, является ли число WN для данных
U
иM
? (этот пункт может не иметь смысла, если предыдущий пункт имеет положительный ответ, и мы не будем строить и проверять все числа доN
).
образцы
U = {4, 1, 5, 2, 0} M = 10
тогда MCAN = 2 (3 не может быть достигнуто)
U = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11} M = 10
тогда MCAN = 21 (все до этого могли быть достигнуты, для 22
нет двух 2
символов всего).