Изменения рейтингов за последние раунды временно удалены. Скоро они будут возвращены. ×

Блог пользователя Ripatti

Автор Ripatti, 13 лет назад, По-русски

Наивное решение за время O(nmk) предлагает делать следующее: положить всевозможные начальные положения робота в массив, а затем, в зависимости от текущей команды, сдвигать их в нужном направлении. На каждом шаге нужно проверять что все ли они находятся в клетке выхода.

Однако наивное решение не проходит по времени.

Авторское решение предполагает ускорение наивного решения при помощи битовых масок.

Все текущие положения робота будем хранить в прямоугольной битовой маске размера n × m. Маска поддерживает следующие операции:

1. Сдвиги влево, вправо, вверх, вниз.
2. Бинарные операции AND и OR.
3. Сравнение в другой маской.

Все эти операции можно реализовать так, чтобы они выполнялись за время O(nm / 32). Для реализации можно использовать массивы размера n × m / 32 или же std::bitset на C++.

Теперь, собственно, как моделировать весь процесс?

Сначала создадим маску base, в которой для каждой проходимой клетки стоит 1, а все остальные биты 0.

Создадим несколько дополнительных масок для каждого из четырех направлений: up1, up2, left1, left2, down1, down2, right1, right2. Маски с индексом 1 хранят клетки, которые находятся у стенки, а маски с индексом 2 хранят все остальные клетки маски base.

Кроме того, заведем еще маску, состоящую из одного бита в клетке выхода - маску E.

Теперь пусть все возможные текущие положения робота задаются маской T. Разобъем все эти положения на 2 подмножества - те, которые находятся у стенки и все остальные. Те, что не у стенки, подвинем в соответствии с текущей командой. Позиции у стенки не изменят своего положения. Теперь объединим два подмножества в одно и получим новую маску T. В виде выражения это выглядит так:

T = ((T and up1) or shift_up(T and up2));

Аналогичные выражения записываются для всех остальных направлений сдвига.

Теперь последовательно выполним все сдвиги, на каждом шагу сравнивая T с E. Как только они станут равны - следует вывести номер команды, после которое это произошло. Если равенства так и не случилось - нужно вывести -1.

Предложенное решение имеет сложность O(nmk / 32). Авторские решения на C++ и на Java без каких либо серьезных оптимизаций работают 0,9 с и 2,3 с соответственно.

  • Проголосовать: нравится
  • +13
  • Проголосовать: не нравится