- •Структуры и алгоритмы обработки данных
- •Алгоритмы. Основные определения
- •От задачи к программе
- •Написание программы.
- •Типы данных, структуры данных и абстрактные типы данных
- •Указатели и курсоры
- •Время выполнения программ
- •Измерение времени выполнения программы
- •Степень (порядок) роста
- •Вычисление времени выполнения программ
- •Линейные абстрактные типы данных атд «Список»
- •Реализация списков посредством массивов
- •Реализация списков с помощью указателей
- •Атд «Стек»
- •Атд «Очередь»
- •Реализация очередей с помощью циклических массивов
- •Нелинейные абстрактные типы данных Деревья
- •Порядок узлов
- •Прямой, обратный и симметричный обходы дерева
- •Помеченные деревья и деревья выражений
- •Представление деревьев с помощью массивов
- •Специальные виды множеств атд “Дерево двоичного поиска”
- •Атд "Словарь", основанный
- •Представление ориентированных графов
- •Атд для ориентированных графов
- •Задача нахождения кратчайшего пути
- •Int **c, // массив стоимостей
- •Int *d) // массив кратчайших
- •Остовные деревья минимальной стоимости
- •Обход графов
- •Поиск в ширину
- •Поиск в глубину
- •Сортировка
- •Простые схемы сортировки Метод «пузырька»
- •Сортировка вставками
- •Быстрая сортировка
- •Пирамидальная сортировка
- •«Карманная» сортировка
- •Порядковые статистики
- •Методы разработки алгоритмов. Типы алгоритмов
- •Алгоритмы «разделяй и властвуй» (метод декомпозиции)
- •Баланс подзадач
- •Динамическое программирование
- •Перемножение нескольких матриц
- •Шаг 1: строение оптимальной расстановки скобок
- •Шаг 2: рекуррентное соотношение
- •Шаг 3: вычисление оптимальной стоимости
- •Void MatrixChainOrder(int n, // кол-во матриц
- •Int p[], // размеры матриц
- •Int **s) // оптимальное k
- •Шаг 4: построение оптимального решения
- •Int **s, // таблица, полученная
- •Int I, // индексы
- •Когда применимо динамическое программирование?
- •Оптимальность для подзадач
- •Перекрывающиеся подзадачи
- •«Жадные» алгоритмы
- •"Жадные" алгоритмы как эвристики
- •Когда применим жадный алгоритм?
- •Принцип жадного выбора
- •Оптимальность для подзадач
- •Поиск с возвратом
- •Функции выигрыша
- •Метод ветвей и границ
- •Структуры данных и алгоритмы для внешней памяти
- •Внешняя сортировка
- •Хранение данных в файлах
- •Простая организация данных
- •Хешированные файлы
- •Индексированные файлы
- •Содержание
- •Глава I. Линейные абстрактные типы данных 31
- •Глава II. Сортировка 108
Функции выигрыша
Идею дерева игры, узлы которого имеют цену –1,0 или 1, можно обобщить на деревья, листьям которых присваиваются любые числа (такое число называется выигрышем) выполняющие роль цены игры. Для оценивания внутренних узлов применяются все те же правила: взять максимум среди потомков на тех уровнях, где предстоит сделать ход игроку 1, и минимум среди потомков на тех уровнях, где предстоит сделать ход игроку 2.
В качестве примера, где удобно применить концепцию выигрышей, сложную игру (например, шахматы), в которой дерево игры, являясь, в принципе конечным, столь огромно, что любые попытки оценить его по методу “снизу вверх” обречены на неудачу. Любые шахматные программы действуют, в сущности, путем построения для каждой промежуточной позиции на шахматной доске дерева игры. Корнем этого дерева является текущая позиция; корень распространяется вниз на несколько уровней. Точное количество уровней не зависит от быстродействия конкретного компьютера. Когда большинство листьев дерева проявляют “неоднозначность” (т.е. не ведут ни к выигрышу, ни к ничьей, ни к проигрышу), каждая программа использует определенную функцию позиций на доске, которая пытается оценить вероятность выигрыша компьютера в этой позиции. Например, на такой оценке в значительной мере сказывается наличие у одной из сторон материального перевеса и такие факторы, как прочность защиты королей.
Используя подобную функцию выигрыша, компьютер может оценить вероятность выигрыша после выполнения им каждого и возможных очередных ходов (в предположении, что игра каждой из сторон будет проходить по оптимальному сценарию) и выбрать ход с наивысшим выигрышем.
Ниже перечислен ряд других правил, в соответствии с которыми действуют хорошие шахматные программы:
-
Использование эвристик, чтобы исключить из рассмотрения определенные ходы, которые вряд ли можно считать хорошими. Это помогает увеличить количество просматриваемых уровней дерева за фиксированное время.
-
Распространение “цепочек взятия”, которые представляют собой последовательности ходов сопровождающиеся взятием фигур противника, за пределы последнего уровня, до которого обычно распространяется дерево. Это помогает более точно оценить относительную материальную силу позиций.
-
Сокращение поиска на дереве методом альфа-бета отсечения (см. дальше в этом разделе)
Метод ветвей и границ
Игры – не единственная категория задач, которые можно решать полным перебором всего дерева возможностей.
Широкий спектр задач, в которых требуется найти минимальную или максимальную конфигурацию того или иного типа, поддаются решению путем поиска с возвратом, применяемого к дереву возможностей. Узлы такого дерева можно рассматривать как совокупности конфигураций, а каждый потомок узла n представляет некоторое подмножество конфигураций.
Наконец, каждый лист представляет отдельную конфигурацию или решение соответствующей задачи; каждую такую конфигурацию можно оценить и попытаться выяснить, не является ли она наилучшей среди уже найденных решений.
Если просмотр организован достаточно рационально, каждый из потомков некоторого узла будет представлять намного меньше конфигураций, чем соответствующий узел, поэтому, чтобы достичь листьев, не придется забираться слишком глубоко.