Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

Алгоритм поиска пути A* (а-стар)

Лекция



Привет, Вы узнаете о том , что такое a*, Разберем основные их виды и особенности использования. Еще будет много подробных примеров и описаний. Для того чтобы лучше понимать что такое a*, а-стар, поиск пути , настоятельно рекомендую прочитать все из категории Алгоритмы и теория алгоритмов.

a* (произносится как « а-стар ») — это алгоритм обхода графа и поиска пути , который используется во многих областях компьютерных наук благодаря своей полноте, оптимальности и оптимальной эффективности При наличии взвешенного графа , исходного узла и целевого узла алгоритм находит кратчайший путь (относительно заданных весов) от источника до цели.

Одним из главных практических недостатков является егоАлгоритм поиска пути A* (а-стар) Сложность пространства , где d — глубина самого поверхностного решения (длина кратчайшего пути от исходного узла до любого заданного целевого узла), а b — фактор ветвления (максимальное количество последователей для любого заданного состояния), поскольку он сохраняет все сгенерированные узлы в памяти. Таким образом, в практических системах маршрутизации путешествий он, как правило, уступает алгоритмам, которые могут предварительно обрабатывать граф для достижения лучшей производительности, , а также подходам с ограничением памяти; однако A* по-прежнему является лучшим решением во многих случаях.

Питер Харт , Нильс Нильссон и Бертрам Рафаэль из Стэнфордского исследовательского института (ныне SRI International ) впервые опубликовали алгоритм в 1968 году. Его можно рассматривать как расширение алгоритма Дейкстры . A* достигает лучшей производительности, используя эвристику для управления поиском.

По сравнению с алгоритмом Дейкстры, алгоритм A* находит только кратчайший путь от указанного источника до указанной цели, а не дерево кратчайших путей от указанного источника до всех возможных целей. Это необходимый компромисс для использования эвристики , направленной на конкретную цель . Для алгоритма Дейкстры, поскольку генерируется все дерево кратчайших путей, каждый узел является целью, и не может быть эвристики, направленной на конкретную цель.

История

Алгоритм поиска пути A* (а-стар)

A* был изобретен исследователями, работавшими над планированием пути робота Шейки.

A* был создан как часть проекта Shakey , целью которого было создание мобильного робота, который мог бы планировать свои собственные действия. Нильс Нильссон изначально предложил использовать алгоритм Graph Traverser для планирования пути Shakey. Graph Traverser руководствуется эвристической функцией h ( n ) , оценочным расстоянием от узла n до конечного узла: он полностью игнорирует g ( n ) , расстояние от начального узла до n . Бертрам Рафаэль предложил использовать сумму, g ( n )+ h ( n ) . Питер Харт изобрел концепции, которые мы сейчас называем допустимостью и согласованностью эвристических функций. A* изначально был разработан для поиска путей с наименьшей стоимостью, когда стоимость пути является суммой его стоимостей, но было показано, что A* можно использовать для поиска оптимальных путей для любой задачи, удовлетворяющей условиям алгебры стоимости.

Оригинальная статья A* 1968 года содержала теорему, утверждающую, что никакой алгоритм типа A* ​​не может расширить меньше узлов, чем A*, если эвристическая функция согласована и правило разрешения конфликтов A* выбрано соответствующим образом. «Исправление» было опубликовано несколько лет спустя , утверждая, что согласованность не требуется, но это было показано ложным в 1985 году в окончательном исследовании оптимальности A* (теперь называемом оптимальной эффективностью) Дектера и Перла, которое дало пример A* с эвристикой, которая была допустимой, но не согласованной, расширяя произвольно больше узлов, чем альтернативный алгоритм типа A*.

Описание

Алгоритм поиска пути A* (а-стар)

Алгоритм поиска пути A*, перемещающийся по случайно сгенерированному лабиринту

Иллюстрация поиска A* для нахождения пути между двумя точками на графике. Слева направо все чаще используется эвристика, которая отдает предпочтение точкам, более близким к цели.

A* — это алгоритм информированного поиска или поиск по принципу «лучший первый» , то есть он сформулирован в терминах взвешенных графов : начиная с определенного начального узла графа, он стремится найти путь к заданному целевому узлу с наименьшей стоимостью (наименьшее пройденное расстояние, кратчайшее время и т. д.). Он делает это, поддерживая дерево путей, начинающихся в начальном узле, и расширяя эти пути по одному ребру за раз, пока не будет достигнут целевой узел.

На каждой итерации своего основного цикла A* необходимо определить, какой из своих путей следует расширить. Он делает это на основе стоимости пути и оценки стоимости, необходимой для расширения пути до цели. В частности, A* выбирает путь, который минимизирует

Алгоритм поиска пути A* (а-стар)

где n — следующий узел на пути, g ( n ) — стоимость пути от начального узла до n , а h ( n ) — эвристическая функция, которая оценивает стоимость самого дешевого пути от n до цели. Эвристическая функция специфична для проблемы. Если эвристическая функция допустима — то есть она никогда не переоценивает фактическую стоимость достижения цели — A* гарантированно вернет путь с наименьшей стоимостью от начала до цели.

Типичные реализации A* используют приоритетную очередь для выполнения повторного выбора узлов с минимальной (оцененной) стоимостью для расширения. Эта приоритетная очередь известна как открытое множество , край или граница . На каждом шаге алгоритма узел с наименьшим значением f ( x ) удаляется из очереди, значения f и g его соседей обновляются соответствующим образом, и эти соседи добавляются в очередь. Алгоритм продолжается до тех пор, пока удаленный узел (таким образом, узел с наименьшим значением f из всех узлов края) не станет целевым узлом. Значение f этой цели затем также является стоимостью кратчайшего пути, поскольку h в цели равно нулю в допустимой эвристике.

Описанный до сих пор алгоритм дает только длину кратчайшего пути. Чтобы найти фактическую последовательность шагов, алгоритм можно легко пересмотреть так, чтобы каждый узел на пути отслеживал своего предшественника. После запуска этого алгоритма конечный узел будет указывать на своего предшественника, и так далее, пока предшественник некоторого узла не станет начальным узлом.

Например, при поиске кратчайшего маршрута на карте h ( x ) может представлять собой расстояние по прямой до цели, поскольку это физически наименьшее возможное расстояние между любыми двумя точками. Для карты-сетки из видеоигры использование расстояния Taxicab или расстояния Чебышева становится лучшим вариантом в зависимости от набора доступных движений (4-х или 8-ми).

Если эвристика h удовлетворяет дополнительному условию h ( x ) ≤ d ( x , y ) + h ( y ) для каждого ребра ( x , y ) графа (где d обозначает длину этого ребра), то h называется монотонной или последовательной . С последовательной эвристикой A* гарантированно найдет оптимальный путь, не обрабатывая ни один узел более одного раза, и A* эквивалентно запуску алгоритма Дейкстры с уменьшенной стоимостью d' ( x , y ) = d ( x , y ) + h ( y ) − h ( x ) .

Алгоритм поиска пути A* (а-стар)Иллюстрация поиска A* для нахождения пути от начального узла до конечного узла в задаче планирования движения робота . Пустые кружки представляют узлы в открытом наборе , т. е. те, которые еще предстоит исследовать, а заполненные кружки находятся в закрытом наборе. Цвет каждого закрытого узла указывает расстояние от цели: чем зеленее, тем ближе. Сначала можно увидеть, как A* движется по прямой в направлении цели, затем, столкнувшись с препятствием, он исследует альтернативные маршруты через узлы из открытого набора.

Пример

Пример алгоритма A* в действии, где узлы — это города, соединенные дорогами, а h(x) — это расстояние по прямой до целевой точки:

Алгоритм поиска пути A* (а-стар)

Обозначения: зеленый: начало; синий: цель; оранжевый: посещение

Алгоритм A* имеет реальные приложения. В этом примере ребра — это железные дороги, а h(x) — это расстояние по дуге большого круга (кратчайшее возможное расстояние на сфере) до цели. Алгоритм ищет путь между Вашингтоном, округ Колумбия, и Лос-Анджелесом.

Алгоритм поиска пути A* (а-стар)

Подробности реализации

Существует ряд простых оптимизаций или деталей реализации, которые могут существенно повлиять на производительность реализации A*. Первая деталь, которую следует отметить, заключается в том, что способ обработки приоритетной очередью связей может существенно влиять на производительность в некоторых ситуациях. Если связи разрываются, и очередь ведет себя в манере LIFO , A* будет вести себя как поиск в глубину среди путей с равной стоимостью (избегая исследования более одного одинаково оптимального решения).

Когда в конце поиска требуется путь, обычно для каждого узла сохраняется ссылка на родителя этого узла. В конце поиска эти ссылки можно использовать для восстановления оптимального пути. Если эти ссылки сохраняются, то может быть важно, чтобы один и тот же узел не появлялся в очереди приоритетов более одного раза (каждая запись соответствует другому пути к узлу, и каждая имеет свою стоимость). Стандартный подход здесь заключается в проверке того, появляется ли уже в очереди приоритетов узел, который должен быть добавлен. Если это так, то указатели приоритета и родителя изменяются, чтобы соответствовать пути с меньшей стоимостью. Стандартная двоичная куча на основе приоритетов напрямую не поддерживает операцию поиска одного из своих элементов, но ее можно дополнить хэш-таблицей , которая сопоставляет элементы с их положением в куче, позволяя выполнять эту операцию уменьшения приоритета за логарифмическое время. В качестве альтернативы куча Фибоначчи может выполнять те же операции уменьшения приоритета за постоянное амортизированное время .

Особые случаи

Алгоритм Дейкстры , как еще один пример алгоритма поиска с равномерной стоимостью, можно рассматривать как частный случай A*, где ⁠Алгоритм поиска пути A* (а-стар)⁠ для всех x .] Общий поиск в глубину может быть реализован с использованием A*, если учесть, что есть глобальный счетчик C, инициализированный очень большим значением. Каждый раз, когда мы обрабатываем узел, мы назначаем C всем его вновь обнаруженным соседям. После каждого назначения мы уменьшаем счетчик C на единицу. Таким образом, чем раньше обнаружен узел, тем выше его Алгоритм поиска пути A* (а-стар)⁠ значение. И алгоритм Дейкстры, и поиск в глубину можно реализовать более эффективно без включения ⁠Алгоритм поиска пути A* (а-стар)⁠ значение в каждом узле.

Характеристики

Прекращение и полнота

На конечных графах с неотрицательными весами ребер A* гарантированно завершается и является полным , т.е. он всегда найдет решение (путь от начала до цели), если оно существует. На бесконечных графах с конечным фактором ветвления и стоимостями ребер, которые отделены от нуля Алгоритм поиска пути A* (а-стар)для некоторых фиксированныхεАлгоритм поиска пути A* (а-стар)), A* гарантированно завершится только в том случае, если существует решение.

Допустимость

Алгоритм поиска считается допустимым , если он гарантированно возвращает оптимальное решение. Если эвристическая функция, используемая A* , допустима , то A* допустим. Интуитивное «доказательство» этого таково:

Назовем узел закрытым, если он был посещен и не находится в открытом множестве. Мы закрываем узел, когда удаляем его из открытого множества. Основное свойство алгоритма A*, доказательство которого мы набросаем ниже, заключается в том, что когда ⁠нАлгоритм поиска пути A* (а-стар)⁠ закрыто, ⁠ Алгоритм поиска пути A* (а-стар)⁠ — это оптимистическая оценка (нижняя граница) истинного расстояния от начала до цели. Поэтому, когда узел цели, ⁠гАлгоритм поиска пути A* (а-стар)⁠ , закрыто, ⁠ Алгоритм поиска пути A* (а-стар)⁠ не больше истинного расстояния. Об этом говорит сайт https://intellect.icu . С другой стороны, оно не меньше истинного расстояния, поскольку оно есть длина пути к цели плюс эвристический термин.

Теперь мы увидим, что всякий раз, когда узел ⁠нАлгоритм поиска пути A* (а-стар)⁠ закрыто, ⁠ Алгоритм поиска пути A* (а-стар)⁠ — оптимистическая оценка. Достаточно увидеть, что всякий раз, когда открытое множество не пусто, оно имеет по крайней мере один узел ⁠нАлгоритм поиска пути A* (а-стар)⁠ на оптимальном пути к цели, для которой ⁠ Алгоритм поиска пути A* (а-стар)⁠ — истинное расстояние от начала, так как в этом случае ⁠ Алгоритм поиска пути A* (а-стар)⁠ + ⁠ Алгоритм поиска пути A* (а-стар)⁠ недооценивает расстояние до цели, и, следовательно, то же самое делает и меньшее значение, выбранное для закрытой вершины. Пусть ⁠Алгоритм поиска пути A* (а-стар)⁠ — оптимальный путь от начала до цели. Пусть ⁠Алгоритм поиска пути A* (а-стар)⁠ быть последним закрытым узлом на ⁠ Алгоритм поиска пути A* (а-стар)⁠ для которого ⁠ Алгоритм поиска пути A* (а-стар)⁠ — истинное расстояние от начала до цели (начало — одна из таких вершин). Следующий узел в ⁠Алгоритм поиска пути A* (а-стар)⁠ имеет правильный ⁠Алгоритм поиска пути A* (а-стар)⁠ значение, так как оно было обновлено, когда ⁠Алгоритм поиска пути A* (а-стар)⁠ был закрыт, и он открыт, поскольку не закрыт.

Оптимальность и последовательность

Алгоритм A оптимально эффективен по отношению к набору альтернативных алгоритмов Alts на наборе задач P , если для каждой задачи P в P и каждого алгоритма A′ в Alts набор узлов, расширенный A при решении P, является подмножеством (возможно, равным) набора узлов, расширенного A′ при решении P. Окончательное исследование оптимальной эффективности A* принадлежит Рине Дехтер и Джуде Перл. [ Они рассмотрели множество определений Alts и P в сочетании с эвристикой A*, которая является просто допустимой или является как последовательной , так и допустимой. Самый интересный положительный результат, который они доказали, заключается в том, что A* с последовательной эвристикой оптимально эффективен по отношению ко всем допустимым алгоритмам поиска типа A* для всех «непатологических» задач поиска. Грубо говоря, их понятие непатологической задачи — это то, что мы теперь подразумеваем под «до разрешения конфликта». Этот результат не выполняется, если эвристика A* допустима, но не последовательна. В этом случае Дектер и Перл показали, что существуют допустимые алгоритмы типа A*, которые могут расширять произвольно меньше узлов, чем A*, на некоторых непатологических проблемах.

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

Ограниченная релаксация

Алгоритм поиска пути A* (а-стар)

Поиск A*, который использует эвристику, которая в 5,0(=ε) раз больше последовательной эвристики , и получает неоптимальный путь

Хотя критерий допустимости гарантирует оптимальный путь решения, это также означает, что A* должен проверить все одинаково достойные пути, чтобы найти оптимальный путь. Чтобы вычислить приблизительные кратчайшие пути, можно ускорить поиск за счет оптимальности, ослабив критерий допустимости. Часто мы хотим ограничить это ослабление, чтобы гарантировать, что путь решения не хуже, чем (1 + ε ) раз от оптимального пути решения. Эта новая гарантия называется ε -допустимой.

Существует ряд ε -допустимых алгоритмов:

  • Взвешенные A*/статические весовые коэффициенты Если h a ( n ) является допустимой эвристической функцией, в взвешенной версии поиска A* используется h w ( n ) = ε h a ( n ) , ε > 1 в качестве эвристической функции, и выполняется поиск A* как обычно (что в конечном итоге происходит быстрее, чем при использовании h a , поскольку расширяется меньше узлов). Таким образом, путь, найденный алгоритмом поиска, может иметь стоимость не более чем в ε раз больше, чем у пути с наименьшей стоимостью в графе.
  • Выпуклая парабола вверх/вниз (XUP/XDP). Модификация функции стоимости во взвешенном A* для продвижения оптимальности к началу или цели. XDP дает пути, которые близки к оптимальным вблизи начала, а пути XUP близки к оптимальным вблизи цели. Оба даютϵАлгоритм поиска пути A* (а-стар)-оптимальные пути в целом.

    Алгоритм поиска пути A* (а-стар).

    Алгоритм поиска пути A* (а-стар).

  • Кусочно-восходящая/нисходящая кривая (pwXU/pwXD). Аналогично XUP/XDP, но с кусочно-последовательными функциями вместо параболы. Пути решения такжеϵАлгоритм поиска пути A* (а-стар)-оптимально.

    Алгоритм поиска пути A* (а-стар)

    Алгоритм поиска пути A* (а-стар)

  • Динамическое взвешивание использует функцию стоимости ⁠ Алгоритм поиска пути A* (а-стар)⁠ , где 0в противном случаеАлгоритм поиска пути A* (а-стар), и где ⁠ Алгоритм поиска пути A* (а-стар)⁠ — глубина поиска, а N — предполагаемая длина пути решения.
  • Выборочное динамическое взвешивание использует выборку узлов для лучшей оценки и устранения эвристической ошибки.
  • Алгоритм поиска пути A* (а-стар). использует две эвристические функции. Первая — это список FOCAL, который используется для выбора узлов-кандидатов, а вторая h F используется для выбора наиболее перспективного узла из списка FOCAL.
  • A ε выбирает узлы с функцией Алгоритм поиска пути A* (а-стар)⁠ , где A и B — константы. Если не удается выбрать ни одного узла, алгоритм возвращается к функции Алгоритм поиска пути A* (а-стар)⁠ , где C и D — константы.
  • AlphA* пытается продвигать глубинную эксплуатацию, отдавая предпочтение недавно расширенным узлам. AlphA* использует функцию стоимости Алгоритм поиска пути A* (а-стар), где Алгоритм поиска пути A* (а-стар), где λ и Λ — константы Алгоритм поиска пути A* (а-стар), π ( n ) является родительским узлом n , а ñ является последним расширенным узлом.

Сложность

Как эвристический алгоритм поиска, производительность A* во многом зависит от качества эвристической функции.Алгоритм поиска пути A* (а-стар). Если эвристика близко приближается к истинной стоимости цели, A* может значительно сократить количество расширений узлов. С другой стороны, плохая эвристика может привести к множеству ненужных расширений.

Наихудший сценарий

В худшем случае A* расширяет все узлынАлгоритм поиска пути A* (а-стар)для которого Алгоритм поиска пути A* (а-стар), гдеАлгоритм поиска пути A* (а-стар)— стоимость оптимального целевого узла.

Почему не может быть хуже?

Предположим, что есть узелАлгоритм поиска пути A* (а-стар)в открытом списке Алгоритм поиска пути A* (а-стар), и это следующий узел, который будет расширен. Поскольку целевой узел имеет

Алгоритм поиска пути A* (а-стар), Алгоритм поиска пути A* (а-стар), целевой узел будет иметь меньшее значение f и будет расширен до Алгоритм поиска пути A* (а-стар).

Поэтому A* никогда не расширяет узлы с помощьюАлгоритм поиска пути A* (а-стар).

Почему не может быть лучше?

Предположим, что существует оптимальный алгоритм, который расширяет меньше узлов, Алгоритм поиска пути A* (а-стар)в худшем случае с использованием той же эвристики. Это означает, что должен быть какой-то узел Алгоритм поиска пути A* (а-стар)такой Алгоритм поиска пути A* (а-стар), однако алгоритм предпочитает не расширять его.

Теперь рассмотрим измененный график, где новое ребро стоимостиАлгоритм поиска пути A* (а-стар)(Алгоритм поиска пути A* (а-стар)) добавляется Алгоритм поиска пути A* (а-стар)к цели. Если Алгоритм поиска пути A* (а-стар), то новый оптимальный путь проходит черезАлгоритм поиска пути A* (а-стар). Однако, поскольку алгоритм по-прежнему избегает расширенияАлгоритм поиска пути A* (а-стар), он пропустит новый оптимальный путь, нарушив его оптимальность.

Следовательно, ни один оптимальный алгоритм, включающий A*, не может расширить меньше узлов, чемАлгоритм поиска пути A* (а-стар)в худшем случае.

Математическая нотация

Худший случай сложности A* часто описывается какАлгоритм поиска пути A* (а-стар), гдебАлгоритм поиска пути A* (а-стар)является фактором разветвления и Алгоритм поиска пути A* (а-стар)глубина самой поверхностной цели. Хотя это дает грубую интуицию, это не отражает точно фактическое поведение A*.

Более точная оценка учитывает количество узлов Алгоритм поиска пути A* (а-стар). ЕслиεАлгоритм поиска пути A* (а-стар)это наименьшая возможная разница в Алгоритм поиска пути A* (а-стар)-стоимость между отдельными узлами, то A* может расширяться до:

О(С∗ε)Алгоритм поиска пути A* (а-стар)

В худшем случае это отражает как временную, так и пространственную сложность.

Сложность пространства

Пространственная сложность A* примерно такая же, как и у всех других алгоритмов поиска по графу, поскольку он сохраняет все сгенерированные узлы в памяти. На практике это оказывается самым большим недостатком поиска A*, что приводит к разработке эвристических поисков с ограничением памяти, таких как итеративное углубление A* , ограниченный памятью A* и SMA* .

Приложения

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

Связь с другими алгоритмами

Отличие A* от жадного алгоритма поиска по лучшему первому заключается в том, что он учитывает стоимость/пройденное расстояние g ( n ) .

Некоторые распространенные варианты алгоритма Дейкстры можно рассматривать как частный случай A*, где эвристикачАлгоритм поиска пути A* (а-стар)для всех узлов; в свою очередь, и Дейкстра, и A* являются частными случаями динамического программирования . Сам A* является частным случаем обобщения ветвей и границ .

A* похож на лучевой поиск , за исключением того, что лучевой поиск сохраняет ограничение на количество путей, которые он должен исследовать.

Варианты

  • В любое время A*

  • Блок А*
  • Д*
  • Поле D*
  • Бахрома
  • Экономия на дополнительных расходах A* (FSA*)
  • Обобщенный адаптивный А* (GAA*)
  • Инкрементный эвристический поиск
  • Сокращенный А*
  • Итеративное углубление A* (IDA*)
  • Поиск точки перехода
  • Планирование на всю жизнь A* (LPA*)
  • Новый двунаправленный A* (NBA*)
  • Упрощенная память с ограничением A* (SMA*)
  • Тета*

A* также можно адаптировать к алгоритму двунаправленного поиска , но необходимо уделить особое внимание критерию остановки.

Вау!! 😲 Ты еще не читал? Это зря!

Исследование, описанное в статье про a*, подчеркивает ее значимость в современном мире. Надеюсь, что теперь ты понял что такое a*, а-стар, поиск пути и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Алгоритмы и теория алгоритмов

создано: 2025-06-21
обновлено: 2025-06-21
13



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей

Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Алгоритмы и теория алгоритмов

Термины: Алгоритмы и теория алгоритмов