Задать вопрос
  • Как решать задачу на булеву логику?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    С помощью тождеств
    not(A and B) = not A or not B
    not(A or B) = not A and not B
    Ответ написан
    Комментировать
  • Как решать задачу с графом?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Рекурсивный перебор в глубину из узлов-выходов, ограниченный временем жизни лабиринта, с обнулением посещённых узлов (можно через список посещённых).
    Запоминаем маршрут с максимальной выгодой, потом разворачиваем его, получая прямой путь.
    Отдельно надо обрабатывать вариант, когда два узла соединены путём с нулевым временем. Тут обход может зациклиться.
    Вариант на PHP

    <?php
    
    /*
     * Комната 0 введена для унификации алгоритма.
     * Из неё можно попаст в любой выход, в неё попасть из других комнат нельзя.
     */
    const NODES = [
        0 => ['battleTime' => 0, 'loot' => 0],
        1 => ['battleTime' => 5, 'loot' => 15],
        2 => ['battleTime' => 2, 'loot' => 1],
        3 => ['battleTime' => 3, 'loot' => 5],
        4 => ['battleTime' => 3, 'loot' => 6],
        5 => ['battleTime' => 4, 'loot' => 7],
        6 => ['battleTime' => 5, 'loot' => 9],
        7 => ['battleTime' => 7, 'loot' => 16],
        8 => ['battleTime' => 2, 'loot' => 3],
        9 => ['battleTime' => 0, 'loot' => 0],
        10 => ['battleTime' => 0, 'loot' => 0],
    ];
    
    const ROUTE_TIMES = [
        0 => [9 => 0, 10 => 0],
        1 => [2 => 1],
        2 => [1 => 1, 8 => 2, 9 => 3, 4 => 1],
        3 => [9 => 2, 4 => 4],
        4 => [3 => 4, 2 => 1, 5 => 3],
        5 => [4 => 3, 10 => 1],
        6 => [10 => 4, 7 => 4],
        7 => [8 => 4, 6 => 4],
        8 => [2 => 2, 7 => 4, 10 => 6],
        9 => [3 => 2, 2 => 3],
        10 => [5 => 1, 8 => 6, 6 => 4],
    ];
    
    const MAX_LIFETIME = 25;
    
    function findRoute(array $state): array
    {
        $bestState = $state;
        foreach (ROUTE_TIMES[$state['currentNode']] as $nextNode => $travelTime) {
            $nodeTime = $state['lifetime'] + $travelTime +
                (in_array($nextNode, $state['route']) ? 0 : NODES[$nextNode]['battleTime']);
            if ($nodeTime > MAX_LIFETIME) {
                continue;
            }
            $nodeState = findRoute([
                'lifetime' => $nodeTime,
                'currentNode' => $nextNode,
                'wealth' => $state['wealth'] + (in_array($nextNode, $state['route']) ? 0 : NODES[$nextNode]['loot']),
                'route' => [...$state['route'], $nextNode],
            ]);
            if ($nodeState['wealth'] > $bestState['wealth']) {
                $bestState = $nodeState;
            }
        }
        return $bestState;
    }
    
    $state = findRoute([
        'lifetime' => 0,
        'currentNode' => 0,
        'wealth' => 0,
        'route' => [],
    ]);
    
    echo "Route: ", implode(' => ', array_reverse($state['route'])), "\n";
    echo "Wealth: ", $state['wealth'], "\n";
    echo "Time: ", $state['lifetime'], "\n";

    Route: 8 => 2 => 1 => 2 => 4 => 5 => 10
    Wealth: 32
    Time: 25
    Ответ написан
    Комментировать
  • Как решать задачу с графом?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Все становится сложно из-за того, что можно второй раз проходить по комнате и при этом не тратить время на гоблина и не получая награды. Мне кажется, можно задачу коммивояжора свести к этой задаче, так что она NP-полная и тут нет быстрого алгоритма. Только перебор или что-то экспоненциальное. Соответственно, оно все работает лишь не небольших гарафах.

    Можно применять тот же прием, что и в задаче коммивояжора - расслоите граф на 2^n слоев. Пуст у вас n вершин в изначальном графе. В новом графе каждая вершина соответсвует подмножеству комнат и одной комнате. Фактически, вершина обозначает, какие комнаты вы обошли и где сейчас находитесь.

    Ребра есть:
    Из вершины ({}, 0) во все вершины ({v},v) ценой goblinTime[v]: это мы можем зайти в лабиринт в любую комнату и должны там гоблина победить.
    Из вершины (S, v) в вершину (S,u) ценой path[v,u], если u в S - это мы идем в ранее посещенную комнату.
    Из вершины (S, v) в вершину (S+{u},u) ценой path[v,u]+goblitTime[u], если u не в S - это мы идем в ранее не посещенную комнату и бъем там гоблина.

    В этом графе на n2^n вершин вам надо найти все кратчайшие пути из начальной ({},0) во все вершины (например, дейкстрой). Потом переберите все вершины в графе (S, v) и, если вершина соответствует комнате с выходом и вы до нее дошли за время не превосходящее время обрушения, то берите сумму количества золота в комнатах в множестве S в качесвте варианта ответа. Из всех них берите максимум.
    Ответ написан
    Комментировать
  • Как решать задачу с графом?

    @alexalexes
    Алгоритм Дейкстры с перебором входных вершин и выходных вершин.
    Нужно оценить две целевые функции каждого маршрута между вершинами - минимальное суммарное время борьбы с гоблинами, вторая целевая функция - получение максимального числа монет. Найти между этими функциями оптимум.
    Длина каждого проложенного маршрута ограничена временем до обрушения подземелья.
    Если оптимум найден, то этот маршрут и есть решение данной ситуации в графе.
    Ответ написан
    1 комментарий
  • Как решать задачу?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    Надо сделать несколько наблюдений: во-первых, нам без разницы, в каком порядке шары на каждом уровне - важны лишь количества там шаров всех 4 цветов. Во-вторых, если на каком-то уровне остались только белые шары - то мы этот уровень больше никогда трогать не будем. В-третьих, что бы мы не делали на одном уровне - это никак не влияет на другие уровни. Поэтому можно их все рассматривать независимо. Надо решить задачу для каждого уровня отдельно и просуммировать количество дней (и единицы, если на уровне можно что-то оставить).

    Рассмотрим теперь один уровень, который описан 4 числами a,b,c,d и нам надо оставить как можно больше шаров белого цвета (их d). За один ход мы можем приравнять к 0 одно из 4 чисел и вычесть по 1 из отсавшихся ненулвевых. Ясно, что нет смысла занулять d. Т.о. за 3 хода мы можем получть 0,0,0,max(0,d-3). Но, например, если у нас было 2 2 2 3, то занулив a и b мы уменьшениями на 1 зануляем и c. Т.е. для маленьких чисел имеет смысл подумать в каком порядке их занулять. Но мне лень даже думать как именно - ведь их всего 3 числа - можно тупо перебрать все 6 перестанвок и выбрать ту, в которой за наименьшее количество ходов мы их все занулим.
    Ответ написан
    6 комментариев
  • Почему не работает программа на C++ с решением задачи об "Игре в жизнь"?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас ошибка в логике: вы меняете поле отдельно в каждой клетке. И потом используете уже поменянные клетки для подсчета количества соседей в следующей клетке. Но в игре жизнь все клетки считаются параллельно.

    Для этого вам понадобится 2 массива map. Один для текущей итерации, и другой для следующей. Или массив должен быть не bool, а int, и там вы должны разными числами помечать живые клетки, которые умрут, живые клетки, пустые клетки и пустые клетки, которые родятся. В первый проход вы считаете соседей и помечаете клетки, а вторым проходом все изменения применяете.

    Кажется, из-за этого у вас там поле никогда не вымирает и программа не останавливается.
    Ответ написан
    1 комментарий
  • Какую и как дообучить модель машинного перевода?

    @rPman
    Не разбираюсь в вопросе, но когда читал про это, самое простое что можно сделать, взять обученную сетку у фейсбука, и изучить документацию по повторению их результата но уже на своих данных
    https://github.com/facebookresearch/fairseq/tree/m...
    Ответ написан
    5 комментариев
  • Как декодировать матрицу?

    wataru
    @wataru Куратор тега Алгоритмы
    Разработчик на С++, экс-олимпиадник.
    В комментариях мы выяснили, что была матрица 3x4 из цифр от 1 до 9. над ней произвели одно из трех действий и выдали результат. Надо по нему восстановить исходную матрицу. Надо решить на одной конкретной матрице.

    Надо попробовать применить все 3 метода и посмотреть, какой из них даст матрицу из цифр 1-9.

    Итак, для случаев "стороны включая элемент" и "стороны не включая элемент" можно восстановить исходную матрицу однозначно перебрав только первый столбец. Потому что посмотрите на любое число в первом столбце. Вы знаете изначальное число там (вы его перебрали) и знаете сумму известных чисел в столбце и числа справа (это вам дано в матрице). Отсюда можно найти число справа. Когда вы восстановили второй столбец, пройдитесь по всем клеткам в нем и из уравнений для значений там восстановите третий столбец и т.д.

    Вот так проделайте для 9^3 вариантов, если по пути получили числа не из диапазона 1-9, то можно дальше не считать, надо пробовать другой вариант для первого столбца.

    Чуть хуже для случая "стороны и диагонали не включая элемент". Все так же переберите 3 числа в первом столбце. Во втором столбце вы получаете 3 уравнения: сумма первых двух чисел известна из числа в первой строке. Сумма всех трех известна из числа для второй строки. Сумма двух последних - из последнего числа. Т.е. вам дано x+y=A, x+y+z=B, y+z=C. Отсюда элементарно z=B-A, x=B-C, y=A+C-B.

    Этот перебор отработает где-то за 1мс - довольно быстро.

    Есть более общий метод. У вас есть матрица из неизвестных, а каждое число в заданной матрице - это правая часть линейного уравнения. Вот составьте матрицу - выпишите эти все линейные уравнения. Методом Гаусса ее преобразуйте в диагональный вид. Какие-то переменные станут свободными - их надо перебрать. Оставшиеся по известным уравнениям посчитать.
    Ответ написан
    Комментировать
  • Как сделать constexpr strtol?

    @dima20155
    you don't choose c++. It chooses you
    Вроде, нет никакой сложности сделать compile-time strtol
    https://godbolt.org/z/z1o7f63K1
    Ответ написан
    8 комментариев
  • Программу для напоминания?

    @armid
    А чем встроенный планировщик заданий не подходит?
    Настраиваем триггер на тот же батник, который выкидывает Alert.

    Плюсы:
    — не громоздкость;
    — бесплатность;
    — без лишнего зоопарка софта.
    Ответ написан
    Комментировать
  • В чем проблема в коде работы с графом?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Зачем делать безсмысленный makeStep? Пускай он возвращает булево значение.

    boolean makeStep(Graph &graph, ValuesTable &table) { .... }


    Не было отрицательных свойств среди вершин - значит пускай вернет true.
    Тогда будет стоп алгоритма. И не надо будет
    делать дополнительных пере-расчетов.
    Ответ написан
    7 комментариев
  • Через какой алгоритм решать эту задачу?

    Adamos
    @Adamos
    Когда не знаешь, как решать задачу программно - это нормально.
    Надо взять листочек и начать решать ее руками.
    12 этаж, есть два варианта - вверх или вниз. Считаем их, получаем этажи, на каждом два варианта...
    Внезапно доходит, что если уже рассматривал варианты для этажа, то второй раз это можно не делать, результаты будут те же.
    Значит, помечаем посещенные этажи - и крутим варианты, отсекая те, которые ведут на уже посещенные.
    Банальной рекурсией, например...
    Из кода осталось только написать функцию, которая выдаст два варианта для текущего номера этажа - по подробной инструкции из задачи.
    Ответ написан
  • Через какой алгоритм решать эту задачу?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Стоя на 12 этаже можно за 1 ход попасть на 23 этах (Вверх) или на 6 этаж (Вниз).
    Стоя на 6 этаже можно за 1 ход попасть на 11 этаж (ВВ) или на 3 этах.
    (и так далее)

    Вот такой граф получается. Немного напоминает Гипотезу Коллатца. За счет минус единички
    адрес меняется четность и есть надежда что мы не зациклимся а все таки куда-то двигаемся.
    Значит можно упорным баловством с кнопками куда-то приехать.

    Вобщем нужен орграф с 70 вершинами и опционально с 2 ребрами для каждой вершины.
    Недостижимые вершины - это этажи куда нельзя будет попасть соотвественно.
    Ответ написан
    4 комментария
  • Что не так с кодом, проверяющим логическую схему?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Во-первых, у вас цикл от 0 до 32 включительно. Т.е. вы на последней, 33-ей итерации пытаетесь преобразовать 0b100000 в bitset, фактически, второй раз учитывая вариант со всеми нолями. Вот почему вы получаете 33 а не 32.

    Во-вторых, у вас ошибка с тем, что вы из bitmask берете биты, которые есть числа 0 и 1 и проводите над ними битовые операции, а не логические. И это у вас там 32-битные числа же! Для | и & оно еще совпадает с вашими ожиданиями, а вот ~ обращает ВСЕ 32 бита числа.

    Поэтому ~(bitset[E] | bOrD) всегда выдаст или -1 или -2. Вы потом это пропустите через or, получите опять же -1 или -2 и в конце преобразуете это в bool. И вот тут-то оно всегда и станет true.

    Чтобы это исправить, или используйте логические операции (||, &&, !), или вместо ~x используйте x^1, или в самом конце возвращайте результат с &1, чтобы значения остальных бит ни на что не влияли.
    Ответ написан
    5 комментариев