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

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

Уважаемые коллеги и гуры :)

Есть всяческие задачки которые можно обобщить так:

  • есть N лампочек;
  • есть M выключателей;
  • каждый из выключателей переключает (!) состояние некоторых (известно каких) лампочек.

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

Стало любопытно — как она решается? Ну кроме перебора (который видимо для 20 выключателей ещё ничего сработает, а дальше уже некруто). Если решение простое, то приветствуются тонкие намёки, чтоб всё-таки слегка подумать. Если сложное — то буду благодарен за ссылку.

Вообще это выглядит как система линейных уравнений на GF(2), но я пока не понял, приближает ли меня это к решению.

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

»
11 лет назад, # |
  Проголосовать: нравится +23 Проголосовать: не нравится

Это самая обычная система уравнений, Вам осталось только придумать матрицу:-)

»
11 лет назад, # |
Rev. 2   Проголосовать: нравится +21 Проголосовать: не нравится

Вы всё правильно сказали. GF(Z2) — это поле по модулю два, состояние всех лампочек — какой-то N-мерный вектор над этим полем. Каждое преобразование — это прибавление одного из M фиксированных векторов. Вас, фактически, спрашивают — Существуют ли a1, a2, ..., aM, такие что start + a1V1 + a2V2 + ... + aMVM = (00...00).

Это задача из линейной алгебры. Надо решить систему из N уравнений для каждого из разрядов в уравнении выше. Делается обычным методом Гаусса, который, к тому же. надо полем по модулю два дико приятно и просто писать на плюсах. Достаточно воспользоваться встроенными битсетами, у которых перегружен оператор ^, обозначающий пресловутое сложение по модулю два. К тому же, сразу получится быстро и оптимально засчёт битового сжатия.

  • »
    »
    11 лет назад, # ^ |
      Проголосовать: нравится +22 Проголосовать: не нравится

    Дошло, спасибо :)

    Непонятно почему, но мне упорно мерещилось что именно из-за GF(2) я не смогу решать систему "как обычную". Но Гаусс-то конечно работает!

    Мне очень стыдно :D

  • »
    »
    11 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Но у битсетов размер задается при компиляции, или есть способ делать это во время выполнения?

    • »
      »
      »
      11 лет назад, # ^ |
        Проголосовать: нравится +16 Проголосовать: не нравится

      Ага, например, написать свой) А если серьезно, то этого сделать нельзя по крайней мере std::bitset не имеет такой функциональности. Можно писать на яве — там можно указывать произвольный размер, а в скорости сильно не уступает.

»
11 лет назад, # |
Rev. 3   Проголосовать: нравится +16 Проголосовать: не нравится

Ещё вопрос связанный, чтоб не плодить постов:

Я вероятно туплю но не могу придумать "красивого" способа генерировать (псевдо)случайную линейно-независимую систему векторов в GF(2).

Т.е. можно генерить следующий случайный вектор после чего проверять не может ли он быть представлен линейной комбинацией уже нагенерённых... Но изящным это не выглядит :)

*Ну, прикидывал вариант — взять базис из N векторов и случайным образом выбирая A и B среди них добавлять B к A... Хм... Правильно ли я понимаю что линейная независимость будет гарантированно сохраняться?

А, ну вроде правильно. Извиняюсь, видимо утомительные выходные плохо влияют на умственные способности*

  • »
    »
    11 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Да, более того ранк матрицы, если все рядом записать, будет сохраняться ибо это элементарное преобразование над столбцами матрицы(как в Гауссе)