
сиаод / Otvety_Saod
.pdf
никакое кодовое слово не является префиксом любого другого кодового слова. Эти коды имеют переменную длину. Алгоритм Хаффмана можно разделить на два этапа:
1)определение вероятности появления символов в файле;
2)нахождение оптимального префиксного кода. На первом этапе необходимо прочитать файл полностью и подсчитать вероятности появления символов в файле (иногда подсчитывают, сколько раз встречается каждый символ). Если при этом учитываются все 256 сим¬волов, то не будет разницы в сжатии текстового или файла иного формата. Далее находятся два символа a и b с наименьшими вероятностями появления и заменяются одним фиктивным символом x, который имеет вероятность появления, равную сумме вероятностей появле¬ния символов a и b. Затем, используя эту процедуру рекурсивно, находится оптимальный префиксный код для меньшего множества символов (где символы a и b заменены одним символом x). Код для исходного множества символов получается из кодов замещающих символов путем добавления 0 или 1 перед кодом замещающего сим¬вола, и эти два новых кода принимаются как коды заменяемых сим¬волов. Например, код символа a будет соответствовать коду x с до¬бавленным нулем перед этим кодом, а для символа b перед кодом символа x будет добавлена единица.
75. Исчерпывающий перебор. Задачи коммивояжера. Задача о назначениях.
Исчерпывающий перебор – генерация всех вариантов из области определения задачи, выбор тех, которые удовлетворяют ограничениям и последующий поиск нужного варианта решения.
Задача коммивояжера: найти кратчайший путь по заданным n городам, чтобы каждый город посещался только один раз и конечным пунктом оказался город, с которого начали движение. Зададим граф, вершины – города, ребра между ними – пути, вес графа – расстояние от города до города. Обход: V1 – V2 - …… - V1. Пример:
Обходы:
a -> b -> c -> d -> a = 18 (2 + 8 + 1 +8); a -> b -> d -> c -> a = 11;
a -> c -> d -> b -> a = 11; a -> c -> b -> d -> a = 23;
a -> d -> c -> b -> a = 18; a -> d -> c -> b -> a = 23.
Выч. сложность O(n!) - n кол-во «городов».
Задача о назначениях:
Имеется n работников, которые должны выполнить n заданий, стоимость выполнения заданий разными работниками различна. Необходимо распределить все задания так, чтобы они были выполнены с наименьшей стоимостью. Один работник не может выполнять две работы. Пример:
|
Задание 1 |
Задание 2 |
Задание 3 |
Задание 4 |
Работник 1 |
9 |
2 |
7 |
8 |
Работник 2 |
6 |
4 |
3 |
7 |
Работник 3 |
5 |
8 |
1 |
8 |
Работник 4 |
7 |
6 |
9 |
4 |
Переборы вариантов: (выбранная последовательность заданий для 4 работников = полученная стоимость)
1, 2, 3, 4 = 9+4+1+4 = 18; 1,2,4,3 = 9+4+8+9 = 30; 1,3,2,4 = 9+3+8+4 = 24; 1,3,4,2 = 26; 1,4,2,3 = 33;
и т.д. Сложность алгоритма = O(n!) .
76. Поиск с возвратом: алгоритм, применение метода к задаче нахождения гамильтонова цикла в графе.
Рассмотрим задачу нахождения путей, проходящих ровно один раз через каждую вершину (а не через каждое ребро) графа. Путь с таким свойством называется гамильтоновым путем, а цикл – гамильтоновым циклом.
Очевидным алгоритмом нахождения гамильтонова пути в графе является полный перебор всех возможностей: генерируем все n! различных последовательностей вершин и для каждой проверяем, определяет ли она гамильтонов путь. Такие действия потребуют по крайней мере n! шагов.
Алгоритм с возвратом:
Строим наше решение последовательно, начиная с пустой последовательности, т.е. последовательности длины 0. Имея некоторое частичное решение < xj,..., xi >, стараемся найти такое допустимое значение xi+1,относительно которого мы не можем сразу заключить, что < xj,..., xi, xi+1 > можно расширить до некоторого решения (а может быть < xj,...,xi,xi+1 > уже является решением). Если такое предполагаемое, но еще не использованное значение xi+i существует, то мы добавляем его к нашему частичному решению и продолжаем процесс для последовательности < xj,..., xi, xi+1 > . Если его не существует, то мы возвращаемся к частичному решению < xj,..., xi _j > и продолжаем наш процесс, отыскивая новое, еще не

использованное допустимое значение xi . Пример:
Двигаемся: 1->2->3->4->5->6 , т.к. невозможно 6->1 (нет общего ребра), 6->5- >4->6->5, но опять нету 5->1, поэтому 5->4->3->… и т.д. В результате получится путь: 1->2->4->6->5->3->1. Алгоритм:
Алгоритм GamiltonCycle(G)
1.for all vϵV do dop[v] <- true
2.x[1] <- v0
3.dop [v0] <- false
4.Gamilton(2)
Gamilton (k)
1.for y <- List (X[k-1]) do
2.if (y = x0) and (k = n+1) 3.then x[k] <- v0; return x
4.else if dop[y] then
5x[k] <- y
6.dop[y] <- false
7.Gamilton (k+1) 8.dop[y] <- true
9.end if
10end if
11end for
77
78.Метод декомпозиции.
Этот метод, называемый также методом «разделяй и властвуй», или методом разбиения, возможно, является самым важным и наиболее широко применимым методом проектирования эффективных алгоритмов. Он предполагает такую декомпозицию (разбиение) задачи размера n на более мелкие задачи, что на основе решений этих более мелких задач можно легко получить решение исходной задачи. В качестве примеров применений этого метода можно назвать сортировку слиянием или применение деревьев двоичного поиска, которые рассматриваются далее. Проиллюстрируем этот метод на хорошо известном примере:

Так, имеются три стержня A, B и C. Вначале на стержень A нанизаны несколько дисков: диск наибольшего диаметра находится внизу, а выше – диски последовательно уменьшающегося диаметра. Цель головоломки – перемещать диски (по одному) со стержня на стержень так, чтобы диск большего диаметра никогда не размещался выше диска меньшего диаметра и чтобы в конце концов все диски оказались нанизанными на стержень B. Стержень C можно использовать для временного хранения дисков. Задачу перемещения n наименьших дисков со стержня A на стержень B можно представить себе состоящей из двух подзадач размера n – 1. Сначала нужно переместить n – 1 наименьших дисков со стержня A на стержень C, оставив на стержне A n-й наибольший диск. Затем этот диск нужно переместить с A на B. Потом следует переместить n – 1 дисков со стержня C на стержень B. Это перемещение n – 1 дисков выполняется путем рекурсивного применения указанного метода. Поскольку диски, участвующие в перемещениях, по размеру меньше тех, которые в перемещении не участвуют, не нужно задумываться над тем, что находится под перемещаемыми дисками на стержнях A, B или C. Хотя фактическое перемещение отдельных дисков не столь очевидно, а моделирование вручную выполнить непросто из-за образования стеков рекурсивных вызовов, с концептуальной точки зрения этот алгоритм все же довольно прост для понимания и доказательства его правильности (а если говорить о быстроте разработки, то ему вообще нет равных). Именно легкость разработки алгоритмов по методу декомпозиции обусловила огромную популярность этого метода; к тому же во многих случаях эти алгоритмы оказываются более эффективными, чем алгоритмы, разработанные традиционными методами.