Я предполагаю, что вы можете получить необходимое ускорение, сделав свою таблицу DP разреженной.Мы можем представить результирующий алгоритм как выполняющий поиск в ширину от 2^D-1
до 0
на графике, где узлы равны 0..2^D-1
, а ребра переходят от x
до x&y
, где y
- этоэлемент массива.Фактически, из-за коммутативности / ассоциативности побитового И, мы можем сжать установленный фронт, потребовав, чтобы x&y
очистил младший бит, установленный в x
.В приведенном ниже коде Python это достигается несколько эффективно при использовании карты zero_index
, но в CI будет использоваться массив (и при необходимости заменять наборы растровыми изображениями или массивами).
import collections
import random
def min_and(seq):
lst = list(seq)
zero_index = collections.defaultdict(lambda: set(lst))
for x in lst:
y = x
while y:
zero_index[y & ~(y - 1)].discard(x)
y &= y - 1
visited = set()
fringe = set(lst)
i = 0
while 0 not in fringe:
visited.update(fringe)
fringe = {
x & y
for x in fringe for y in zero_index[x & ~(x - 1)]
if x & y not in visited
}
i += 1
return i + len(lst) - 1
print(min_and(
random.randrange(2**18) | random.randrange(2**18) | random.randrange(2**18)
for i in range(100)))