Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...
Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...
Топ:
Эволюция кровеносной системы позвоночных животных: Биологическая эволюция – необратимый процесс исторического развития живой природы...
Установка замедленного коксования: Чем выше температура и ниже давление, тем место разрыва углеродной цепи всё больше смещается к её концу и значительно возрастает...
Выпускная квалификационная работа: Основная часть ВКР, как правило, состоит из двух-трех глав, каждая из которых, в свою очередь...
Интересное:
Влияние предпринимательской среды на эффективное функционирование предприятия: Предпринимательская среда – это совокупность внешних и внутренних факторов, оказывающих влияние на функционирование фирмы...
Принципы управления денежными потоками: одним из методов контроля за состоянием денежной наличности является...
Лечение прогрессирующих форм рака: Одним из наиболее важных достижений экспериментальной химиотерапии опухолей, начатой в 60-х и реализованной в 70-х годах, является...
Дисциплины:
2020-05-07 | 83 |
5.00
из
|
Заказать работу |
|
|
До сих пор рассмотрены только задачи, в которых на каждом шаге выбор решения ограничивался только двумя альтернативами – например, движения вниз или вправо.
Большее количество альтернатив на каждом шаге чаще всего приводит к тому, что перебор всех возможных альтернатив, то есть выбор оптимальной траектории из всех, становится невозможным даже для небольшого числа шагов. Иногда число шагов становится изменяемым в зависимости от принятых решений.
1.5.1. Общая задача нахождения кратчайшего пути (Shortest Path)
Рис. 19. Пример графа для задачи кратчайшего пути
Рассмотрим граф, в котором дуги имеют длины. Требуется определить длину кратчайшего пути из одного узла в другой. Прямое решение, основанное на минимизации отдельных шагов может дать неверный результат: например, выбрав в узле (1) путь в узел (3), можно пропустить кратчайший: (1, 2, 5).
Формально задача описывается так. Имеется граф G(V, E) с узлами vi i=1,... n и дугами ej, которые попарно соединяют некоторые узлы. Каждой дуге приписано неотрицательное число – «длина дуги».
В задаче нужно построить матрицу L размером n ´ n, где L(i, j) является кратчайшим расстоянием между узлами i и j графа.
Алгоритм, который решает задачу, конструирует последовательность матриц L0, L1,..., Lk,..., Ln.
Lk (i, j) представляет кратчайший путь из i в j при условии, что путь может использовать только промежуточные узлы v1... vk.
По способу задания последовательности Ln = L и будет решением задачи.
L0 инициализируется так:
L0 (i, i) = 0;
L0 (i, j) = расстоянию между i и j; или + ¥, если между ними дуги нет.
Предположим, мы сконструировали Lk для любого k < n. Как теперь построить Lk+1?
Как и во всех задачах динамического программирования используется идея разделения на две части. Кратчайший путь от i до j только с узлами v1... vk+1:
|
1) может не содержать vk+1, тогда Lk+1(i, j) = Lk(i, j).
2) содержит vk+1, тогда Lk+1(i, j) = Lk (i, k+1) + Lk (k+1, j).
Из двух возможностей нужно выбрать наименьшую, она и даст кратчайшее расстояние.
Lk+1 (i, j) = min (Lk (i, j), Lk (i, k+1) + Lk(k+1, j))
При реализации алгоритма оказывается достаточно только одной матрицы L размером n ´ n, так как после построения Lk+1 матрица Lk оказывается больше ненужной.
Рис. 20. Программа нахождения минимального пути
# define L(i,j) A[i][j]
void shortest_path_length (int *A[], int n)
{
for (int k=1; k<=n; k++)
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
if (i!= k && j!=k && L(i, j) > L(i, k)+L(k, j))
L(i,j) = L(i,k)+L(k,j);
}
Этот алгоритм для выполнения требует порядка O(n^3) операций.
Эту же идею можно использовать для построения числа путей, ведущих из узла i в узел j. Для этого L0(i, j) инициализируется так:
L0(i, j) = 0, если пути из i в j нет;
L0(i, j) = 1, если путь есть.
Рис. 21. Программа нахождения числа путей в графе
for (int k=1; k<=n; k++)
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
if (i!= k && j!=k)
L(i,j) += L(i,k)*L(k,j);
Последнее произведение – из общего принципа комбинаторики: если из i в k ведет l путей, а из k в j – m, то общее число путей из i в j составит l ´ m.
Сжатие информации с использованием словарного метода
Словарь – список таких слов, которые, как ожидается, будут часто использоваться в текстах. В исходном тексте группы последовательных символов, которые есть в словаре, при сжатии заменяются на индекс этого «слова» в словаре[6]. Задача – произвести такую замену, чтобы в результате текст стал самым коротким. Индексы в примерах показывают номер заменяемого слова в словаре.
Например, словарь: { ab, bde, efg }, текст: babeefg, замена дает: «b 1 e 3», то есть текст разбивается на b- ab- e- efg. Если в тексте 7 символов, то после сжатия остается 4.
Стратегии разбора
Может существовать несколько вариантов выбора слов в исходном тексте. Метод разбиения текста на слова называется разбором. Наиболее простым подходом является тщательный разбор, когда с начала текста на каждом шаге в словаре ищется самая длинная строка, которой соответствует текущая разбираемая строка текста. Тщательный разбор не обязательно будет оптимальным.
|
Например, словарь: { ab, bdef }, текст: abdef тщательный разбор дает: «ab- d- e- f» – четыре символа, а оптимальный – «a- bdef» – два символа. То есть в оптимальном разборе мы отказались на первом шаге получить самый большой выигрыш.
Другая стратегия разбора – отыскать в тексте самое длинное слово из словаря, затем так же поступить с оставшимися частями текста.
Например, для словаря { aa, aaaa, ab, baa, bccb, bccba } и текста aaabccbaaaa такая стратегия сначала определяет bccba как самый длинный фрагмент, имеющийся в словаре. Окончательный разбор строки: «a a- a- bccba- aa- a», то есть текст кодируется 5-ю символами. Тщательный разбор дает «aa-ab-c-c-baa-aa» 6 символов, тогда как оптимальный разбор есть «aa-a-bccb-aaaa» – 4 символа.
Возникает вопрос, как найти оптимальный разбор из всех существующих? Здесь также помогает метод динамического программирования. Пусть разбираемый текст имеет длину m. В каждой букве текста может быть выбор – варианты разбиения. Например, в словаре есть { abcd, ab,...}.
Обозначим L(m) длину оптимального разбиения последних m символов текста.
Таблица 3. Определение оптимального разбора строки текста
Текст | abcdefgh | Длина разбора | L(8) |
вар. 1 | abcd -разбор(efgh) | 1 + разбор efgh | 1+ L(4) |
вар. 2 | ab -разбор(cdefgh) | 1 + разбор cdefgh | 1+ L(6) |
вар. 3 | a -разбор(bcdefgh) | 1 + разбор bcdefgh | 1+ L(7) |
Формула, определяющая длину разбора:
L(8) = 1 + min(L(4), L(6), L(7))
Понятно, что можно так же, как и в остальных задачах динамического программирования идти двумя путями: прямым ходом (рекурсивно) и обратным ходом. Во втором случае разбор начинается справа – для текста длиной 1, 2,...
Очевидно, для текста длиной в один символ L(1) = 1.
Для текста длиной m (m = 2...) нужно перебрать возможные с его начала слова и найти наименьший разбор остальной части.
L(m) = 1 + min (L(m-l1), L(m-l2),...)
1.6. Применение динамического программирования в теории игр на примере игры Ним
Ним – математическая игра[7], в которой два игрока по очереди вынимают предметы из кучек. За один ход может быть взято любое количество предметов (большее нуля) из одной кучки. В стандартном варианте игры выигрывает тот, кто берёт последний предмет, а число кучек равно трём. Эта игра появилась в Китае, название ей дал Чарльз Бутон, который разработал современную математическую теорию.
|
Однако, как показывает анализ, реализация стратегии игры вполне возможна и на основе динамического программирования. В этой игре при начальном распределении предметов по кучкам I, J, K возможно I ´ J ´ K различных состояний игры. В некоторых состояниях у игрока, который выполняет ход, не существует стратегии, которая приведет к выигрышу, например, в конце игры при распределении по кучкам (0, 0, 1) у игрока единственный ход, и он приводит к проигрышу. Обозначим такие состояния знаком «–».
В других состояниях у игрока может существовать ход, который приведет игру в состояние «–» для противника, а, значит, гарантирует при дальнейшей правильной игре выигрыш, например состояние (0, 0, 2) – достаточно взять один предмет из последней кучки, и выигрыш гарантирован. Эти состояния обозначим знаком «+».
Матрица состояний игры w(i, j, k) может быть легко построена, исходя из следующих соображений:
1. w(i, j, k) = w(j, i, k) = w(k, i, j) =... и т.д. в силу того, что ни у одной кучки нет преимуществ, поэтому можно получать w(i, j, k) только для i<= j<= k.
2. w(0,0,1) = «–»
3. w (i, j, k) = «+», если существует такое m, что w(i- m, j, k), w(i, j- m, k) или w(i, j, k- m) = «–», в противном случае w(i, j, k) = «–».
Программа заполнения таблицы и выполнения оптимального представлена на (Рис. 23).
Задание. Построить матрицу состояний для игры с двумя кучками по 4 предмета (решение на Рис. 22).
Рис. 22. Матрица состояний игры Ним для двух кучек
w | 0 | 1 | 2 | 3 | 4 |
0 | + | – | + | + | + |
1 | – | + | + | + | + |
2 | + | + | – | + | + |
3 | + | + | + | – | + |
4 | + | + | + | + | – |
Очевидно, что выигрышной стратегией для такой матрицы является следующая: для любого состояния (i, j) ищется по строке или столбцу состояние '–', если оно существует, то выбираются предметы в первой (по строке) или второй (по столбцу) кучке, чтобы достичь такого состояния. Если в строке или столбце '–' не существует, это значит, что мы сейчас находимся в таком состоянии '–', при любой нашей игре и при правильной игре противника мы проиграем.
Рис. 23. Нахождение оптимального хода для игры Ним
|
void init () // Инициализация
{
w[0][0][0] =’+’;
w[0][0][1] = w[0][1][0] = w[1][0][0] = ’–’;
for (i=0; i<=N; i++)
for (j=0; j<=i; j++)
for (k=0; k<=j; k++)
{
c = ’–’;
for (m = 0; m<i; m++)
if (w[m][j][k]== ’–’) c = ’+’;
for (m = 0; m<j; m++)
if (w[i][m][k]== ’–’) c = ’+’;
for (m = 0; m<k; m++)
if (w[i][j][m]== ’–’) c = ’+’;
w[i][j][k] =
w[i][k][j] =
w[k][i][j] =
w[j][i][k] =
w[k][j][i] =
w[j][k][i] = c;
}
}
void step (int &i, int &j, int &k) // Выполнение хода
{
if (w[i][j][k]==’–’)
{
if (i) i--; else if (j) j--; else if (k) k--;
return;
}
int m;
for (m = 0; m<i; m++)
if (w[m][j][k]== ’–’) {i = m; return;}
for (m = 0; m<j; m++)
if (w[i][m][k]== ’–’) {j = m; return;}
for (m = 0; m<k; m++)
if (w[i][j][m]== ’–’) {k = m; return;}
}
При компьютерной реализации данной модели динамического программирования для того, чтобы интерес у человека-противника сохранялся (это возможно, пока существует потенциальная возможность обыграть программу), в модель введена «сила игры» компьютера. В зависимости от нее программа определенную долю ходов может выполнять случайным образом, в том числе, при нулевой силе игры все ходы программы оказываются случайными, выполняющимися в рамках правил.
Задание. Изменить текст программы, чтобы она могла играть с четырьмя кучками предметов.
|
|
Состав сооружений: решетки и песколовки: Решетки – это первое устройство в схеме очистных сооружений. Они представляют...
Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций...
Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...
Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначенные для поддерживания проводов на необходимой высоте над землей, водой...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!