Ответы пользователя по тегу Алгоритмы
  • Как составить программу "Расставить знаки арифметических операций и скобки чтобы выполнялось равенство"?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    И нехилый такой переборчик получается.
    В варианте "расставить знаки и скобки в левой части, чтобы выполнилось равенство":
    Пусть строка цифр в левой части имеет длину n.
    1. Разбить всеми возможными способами строку на числа. То есть получаем от 1 до n чисел. Количество вариантов разбиения строки из n цифр на m чисел
    mwvtag8.png
    2. Так как в условии сказано про скобки, то операции могут выполняться в разном порядке. Для указания порядка операций по каждому массиву из m чисел можно построить бинарное дерево, используя элементы массива как листья. Каждое дерево будет содержать m-1 вершину. Количество таких деревьев (число Каталана)
    loo5xnj.png
    3. Каждая из вершин задаёт одну из четырёх математических операций (+, -, *, /). Таким образом, количество возможных формул для одного дерева
    kmr2zxr.png
    4. Если добавить унарные минусы, то их можно раставить для каждого из m листьев
    m57sarh.png
    Итого вариантов
    n546hm7.png
    После этого обходом дерева выполняем расчёт и, если результат правильный, выводим дерево в виде выражения со скобками. Вот количество вариантов для разных n (хотя часть из них и окажется дублями или математически неверными из-за деления на 0).
    +----+---------------------+---------------------+
    |  n | без унарных минусов | с унарными минусами |
    +----+---------------------+---------------------+
    |  1 |                   1 |                   2 |
    |  2 |                   5 |                  18 |
    |  3 |                  41 |                 290 |
    |  4 |                 320 |               5'938 |
    |  5 |               5'073 |             136'770 |
    |  6 |              64'469 |           3'379'794 |
    |  7 |             859'385 |          87'547'746 |
    |  8 |          11'853'949 |       2'345'800'050 |
    |  9 |         167'763'361 |      64'477'920'386 |
    | 10 |       2'422'342'053 |   1'807'930'569'874 |
    +----+---------------------+---------------------+

    Мне кажется, или действительно перебор? :-)
    Ответ написан
  • В чем проблема с использованием алгоритма Брезенхэма?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    А в Octave рисуются отдельные точки или линии между точками? Ваша реализация алгоритма, для отрезка (0, 0) - (2,3) выводит:
    2 3
    0 0
    1 1
    1 2

    То есть, если задана отрисовка отрезков, то сначала отрезок (2, 3) - (0, 0), затем (0, 0) - (1, 1) и т.д.
    Для нормального вывода перенесите в конец программы строку
    print ("%d %d" %(x2, y2))
    Ответ написан
    5 комментариев
  • Как найти максимальную сумму, которую можно получить сложением произвольной неразрывной последовательности элементов массива?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    int sum = 0;
    int maxSum = 0;
    for (int i = 0; i < len; i++) {
        sum += val[i];
        if (sum > maxSum)
            maxSum = sum;
        if (sum < 0)
            sum = 0;
    }
    Ответ написан
    Комментировать
  • Алгоритм Флойда-Уоршелла

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Прогнал вашу реализацию с выводом на каждом шаге - всё работает.
    Исходный массив
    0  8  0  0  10
    8  0  4  0  0
    0  4  0  6  16
    0  0  6  0  2
    10 0  16 2  0
    -- Шаг 1 -----
    0  8  0  0  10
    8  0  4  0  18
    0  4  0  6  16
    0  0  6  0  2
    10 18 16 2  0
    -- Шаг 2 -----
    0  8  12 0  10
    8  0  4  0  18
    12 4  0  6  16
    0  0  6  0  2
    10 18 16 2  0
    -- Шаг 3 -----
    0  8  12 18 10
    8  0  4  10 18
    12 4  0  6  16
    18 10 6  0  2
    10 18 16 2  0
    -- Шаг 4 -----
    0  8  12 18 10
    8  0  4  10 12
    12 4  0  6  8
    18 10 6  0  2
    10 12 8  2  0
    -- Шаг 5 -----
    0  8  12 12 10
    8  0  4  10 12
    12 4  0  6  8
    12 10 6  0  2
    10 12 8  2  0

    Так что придётся Вам всё же лезть в дебаг и смотреть, что происходит и что идёт не так именно в вашей системе.
    Ответ написан
  • Как в игре "Жизнь" определить предыдущее состояние клеток по текущему? (Одномерное поле)?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Верно так:
    // Инициализируем C, надо заменить на ввод исходных данных
    $C = array(1, 1, 1, 0, 0, 1, 1, 1, 0, 1);
    $N = count($C);
    
    // Добавляем в начало и конец нули
    array_unshift($C, 0);
    $C[] = 0;
    
    // Создаём массив P, заполняем 0 и N+1 элементы нулями
    $P[0] = 0;
    $P[$N+1] = 0;
    
    // Заполняем чётные ячейки
    for ($i = 1; $i <= $N; $i += 2)
        $P[$i+1] = $P[$i-1] ^ $C[$i];
    
    // Заполняем нечётные ячейки
    if (($N&1) == 0) {
        // Вариант с чётным количеством ячеек
        for ($i = $N; $i >= 1; $i -= 2)
            $P[$i-1] = $P[$i+1] ^ $C[$i];
    } else {
        // Вариант с нечётным количеством ячеек
        $P[1] = 0;
        for ($i = 1; $i <= $N; $i -= 2)
            $P[$i-1] = $P[$i+1] ^ $C[$i];
    }
    
    // Выводим результат
    for ($i = 1; $i <= $N; $i++)
        print $P[$i];

    Получаем 0110100111.
    Проверяем, (0110100111) даёт по правилам (1110011101)
    Ответ написан
    1 комментарий
  • Как в игре "Жизнь" определить предыдущее состояние клеток по текущему? (Одномерное поле)?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Обозначим текущее состояние как C[1..N], предыдущее как P[1..N], С[0] = P[0] = C[N+1] = P[N+1] = 0 - клетки за пределами поля.
    На текущем шаге клетка жива тогда и только тогда, когда на предыдущем шаге у неё был ровно один сосед, то есть C[i] = P[i-1] xor P[i+1] => P[i+1] = C[i] xor P[i-1].
    1. P[0] = 0, C[1] известна => P[2] = P[0] xor C[1]. Теперь, зная P[2] можно найти P[4] = P[2] xor C[3] или в общем случае:
    для i от 1 до N с шагом 2
        P[i+1] = P[i-1] xor C[i];
    Получили все предыдущие значения чётных ячеек.

    2a. Для чётных N обратным ходом можно восстановить нечётные ячейки:
    для i от N до 1 с шагом -2
        P[i-1] = P[i+1] xor C[i];

    2b. Для нечётных N однозначного решения нет. В зависимости от значения P[1] будет получен один из двух вариантов решения:
    P[1] = 0; // или 1
    для i от 2 до N с шагом 2
        P[i+1] = P[i-1] xor C[i];
    Ответ написан
    7 комментариев
  • Задача расчета расстояния путей между городами с использование графов в C++?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Самое простое - двумерный массив w[N][N], где w[i][j] - стоимость перехода из узла i в узел j или -1 если такого пути нет. Если узлов много, а связность низкая, то надо уже копать в сторону разреженных массивов.
    Ответ написан
    Комментировать
  • Какой алгоритм использовать лля определения доступности временного промежутка?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Поразмыслив пришёл к варианту:
    SELECT count(*) AS x FROM records 
        WHERE (begin BETWEEN '{$newRecordBegin}' AND '{$newRecordEnd}') OR
              ('{$newRecordBegin}' BETWEEN begin AND end)

    Первая часть условия - начало какой-либо старой записи попадает в середину новой.
    Вторая часть - начало новой записи попадает в середину какой-либо старой .
    Если хоть одно условие выполнено - count(*) > 0, вставлять запись нельзя.
    Ответ написан
    Комментировать
  • Какой алгоритм использовать лля определения доступности временного промежутка?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    0. Пытаемся вставить новую запись newRecordStart, newRecordLength
    1. Получаем две ближайшие по времени записи, одну до (prevRecordStart, prevRecordLength) и одну после новой (nextRecordStart, nextRecordLength).
    2. Новая запись не должна пересекаться с предыдущей:
    (newRecordStart >= prevRecordStart+prevRecordLength)
    3. Новая запись не должна пересекаться со следующей:
    (newRecordStart+newRecordLength <= nextRecordStart)
    4. Если оба условия выполнены - можно вставлять запись.
    Ответ написан
    Комментировать
  • Анализ данных с термодатчиков и трубки Флейша?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    С температурами всё достаточно просто, графики без шумов. Можно брать локальные минимумы/максимумы, просто перебираете весь массив считая разницу между значениями в текущей и в следующей точках меняет знак, то записываете точку как локальный экстремум.

    d = V[1]-V[0];
    for (i = 1; i < N-1, i++) {
        d1 = V[i+1]-V[i];
        if (d < 0 && d1 > 0) {
            // Локальный минимум V[i]
        } else if (d > 0 && d1 < 0) {
            // Локальный максимум V[i]
        }
        d = d1;
    }

    Для объёма график с шумами, если уровень шумов заранее известен, то его можно исключить игнорируя разницу, попадающую в уровень шума. Для нахождения середины перегиба в этом случае можно анализировать два перехода - от повышения к нулю и от нуля к снижению (наоборот для нижнего перегиба) и брать значение в середине перегиба или среднее значение между крайними точками перегиба.

    noise = 2; // Уровень шума, поставить нужное значение
    t1 = 0; // Точка перехода к нулю
    upDown = 0; // Направление движения до нуля, > 0 - вверх, < 0 - вниз, 0 - начало графика
    d = V[1]-V[0];
    if (abs(d) < noise)
        d = 0;
    for (i = 1; i < N-1, i++) {
        d1 = V[i+1]-V[i];
        if (abs(d1) < noise)
            d1 = 0;
        if (d < 0 && d1 > 0) {
            // Локальный минимум V[i]
        } else if (d > 0 && d1 > 0) {
            // Локальный максимум V[i]
        } else if (d != 0 && d1 == 0) {
            t1 = i;
            upDown = d;
        } else if (d == 0 && d1 > 0 && upDown < 0) {
            // Локальный минимум V[(t1+i)/2] или (V[t1]+V[i])/2
        } else if (d == 0 && d1 < 0 && upDown > 0) {
            // Локальный максимум V[(t1+i)/2] или (V[t1]+V[i])/2
        }
        d = d1;
    }
    Ответ написан
    2 комментария