NetNado
  Найти на сайте:

Учащимся

Учителям



1. /_Методички/Мультимедиа-системы. Архитектура, стандарты, алгоритмы.pdf
2. /_Методички/Организация ЭВМ 2006.doc
3. /_Методички/Основы сетевых технологий.djvu
4. /_Методички/Программирование/Биные Деревья Поиска/2_01БДПоиска.doc
5. /_Методички/Программирование/Биные Деревья Поиска/2_02БинДП.doc
6. /_Методички/Программирование/Биные Деревья Поиска/2_03СлучайБДП.doc
7. /_Методички/Программирование/Деревья Хаффмана/1.doc
8. /_Методички/Программирование/Деревья Хаффмана/1_1ДХафф.doc
9. /_Методички/Программирование/Деревья Хаффмана/1_2_3_ДХафф.doc
10. /_Методички/Программирование/Деревья Хаффмана/1_4_ДХафф.doc
11. /_Методички/Программирование/Деревья Хаффмана/1_5_ДХафф.doc
12. /_Методички/Программирование/Деревья Хаффмана/1_6_7_ДХафф.doc
13. /_Методички/Программирование/Деревья Хаффмана/1_8ДХафф.doc
14. /_Методички/Программирование/Деревья Хаффмана/1_9ДХафф.doc
15. /_Методички/Программирование/Деревья Хаффмана/ДерХафф full.doc
16. /_Методички/Программирование/Деревья Хаффмана/КарлКлара.doc
17. /_Методички/Программирование/Деревья Хаффмана/Кодируется текст АБРАКАДАБРА.doc
18. /_Методички/Программирование/Динамические СД/00Титул.rtf
19. /_Методички/Программирование/Динамические СД/0Введение.rtf
20. /_Методички/Программирование/Динамические СД/1Списки.doc
21. /_Методички/Программирование/Динамические СД/2СтекОчДек1.rtf
22. /_Методички/Программирование/Динамические СД/3Деревья.rtf
23. /_Методички/Программирование/Динамические СД/4прим_лит.rtf
24. /_Методички/Программирование/Динамические СД/5оглавление.doc
25. /_Методички/Программирование/Динамические СД/Динамическое программирование - Задача о перемножении матриц.doc
26. /_Методички/Программирование/Пособие по разработке корректных программ/00Титул1_3.doc
27. /_Методички/Программирование/Пособие по разработке корректных программ/01Введение.rtf
28. /_Методички/Программирование/Пособие по разработке корректных программ/1АлгоритмЕвклида.doc
29. /_Методички/Программирование/Пособие по разработке корректных программ/2ОсновыАналитВерифПрогРовно.doc
30. /_Методички/Программирование/Пособие по разработке корректных программ/3ИндуктФункции.doc
31. /_Методички/Программирование/Пособие по разработке корректных программ/4Массивы.doc
32. /_Методички/Программирование/Пособие по разработке корректных программ/5Поиск.doc
33. /_Методички/Программирование/Пособие по разработке корректных программ/ОглавФонар.doc
34. /_Методички/Программирование/Пособие по разработке корректных программ/СписЛит&УслОбознач.doc
35. /_Методички/Сетевые технологии.pdf
36. /_Методички/Средства моделирования вычислительных сетей.pdf
37. /_Методички/Управление вычислительными сетями.pdf
Учебное пособие Редактор А. В. Крейцер Издательство спбгэту «лэти» 1 97376, С. Петербург, ул. Проф. Попова, 5
2. Деревья поиска Идеально сбалансированные бинарные деревья
2 Случайные бинарные деревья поиска
Абракадабра!, содержащий 12 символов, включая специальный символ !
Задача кодирования сообщений. Префиксные коды и деревья Пусть задан алфавит
1 Код Фано-Шеннона
1 Метод Хаффмана
1 Реализация алгоритмов кодирования
1 Доказательство оптимальности кода Хаффмана Лемма 1
1 Энтропийная оценка средней длины кода
1 Динамическое кодирование по Хаффману
Абракадабра!, содержащий 12 символов, включая специальный символ !
Абракадабра!, содержащий 12 символов, включая специальный символ !
А. Ю. Алексеев с. А. Ивановский д. В. Куликов
При обучении программированию особую трудность вызывает работа с динамическими структурами данных
2. стеки и очереди спецификация стека и очереди
3 Определения дерева, леса, бинарного дерева. Скобочное представление
Примечания и библиографические указания
Списки
Задача о порядке перемножения матриц
С. А. Ивановский разработкакорректныхпрограм м санкт-Петербург 2003
Программирования
Разработка, доказательство корректности и анализ алгоритма
2. основы аналитической верификации программ основные правила аналитической верификации программ
3. индуктивные функции на последовательностях
4. корректность программ при работе с массивами
5. поиск в массиве линейный поиск
Разработка, доказательство корректности
Шень А. Программирование: теоремы и задачи: Учеб пособие

скачать doc


Динамическое программирование

Задача о порядке перемножения матриц
Рассмотрим произведение матриц M1  M2  M3  ...  M1  Mn. Каждая матрица Mi имеет размер r1  ri. Вычисление произведения двух матриц – размер первой l  m и размер второй m  n – требует l m n умножений их элементов. Общее количество элементарных операций умножения, требуемое при вычислении произведения цепочки матриц, зависит от порядка, в котором производятся попарные умножения матриц. Требуется найти такой порядок перемножения матриц, который минимизирует общее количество элементарных операций умножения.

Рассмотрим пример M1  M2  M3  M4, где M1 имеет размер 1020, M2  2050, M3  501, а M4  1100. Если умножения происходят в порядке, соответствующем расстановке скобок M1  (M2  (M3  M4)), то потребуется 125000 умножений, а если это же произведение вычислять как (M1  (M2  M3))  M4, то потребуется всего 2200 умножений.

Пусть mij – оптимальное количество умножений, требуемое для вычисления произведения цепочки матриц M(ij) = Mi  Mi +1  ...  M1  Mj, где 1   n. Очевидно, что M(ii) = Mi и mii = 0, а m1n – соответствует решению задачи для исходной цепочки M(1, n) . При 1   n справедливо следующее рекуррентное соотношение

mij = Min { mik + mk +1,j + r1  rk  rj  j}. (*)

Действительно, при оптимальном вычислении M(ij) последним будет перемножение ранее вычисленных матриц M(ik) и M(k +1, j) при некотором k, таком, что   j. Это перемножение потребует r1  rk  rj операций умножения. В свою очередь M(ik) и M(k +1, j) также должны вычисляться оптимальным способом, т. е. за mik и mk +1,j умножений соответственно.

Заметим, что в правой части равенства (*) разности индексов i – k и j – k –1 у слагаемых mik и mk +1,j меньше, чем разность индексов i – j  в mij. Таким образом, рекуррентное соотношение (*) следует решать, начиная с mii = 0 и последовательно увеличивая разность индексов i – j, до тех пор, пока не получим m1n.

Удобно представлять результаты вычислений в виде таблицы. В этой таблице строка с номером l состоит из ячеек T(ij), индексы которых связаны соотношением i – j = l. Таким образом, в ячейках этой строки j = i + l и T(ij) = T(ii + l), при этом номер i ячейки в строке принимает значения от 1 до n – l  и всего в строке имеется n – l  ячеек: T(1, 1 + l), T(2, 2 +l), …, T( ln).



l = 0

Т(1, 1)

Т(2, 2)

Т(3, 3)

Т(4, 4)



Т(n1, n1)

Т(n, n)

l = 1

Т(1, 2)

Т(2, 3)

Т(3, 4)



Т(n2, n1)

Т(n 1, n)




l = 2

Т(1, 3)

Т(2, 4)



Т(n3, n1)

Т(n2, n)


























l = n –3

Т(1, n2)

Т(2, n1)

Т(3, n)













l = n –2

Т(1, n1)

Т(2, n)
















l = n –1

Т(1, n)




















В ячейках таблицы T(ij) будем хранить вычисленное значение mij и то значение qij = k в диапазоне   j, при котором был получен Min{mik + mk +1,j + r1  rk  rj}. Следующий алгоритм вычисляет оптимальное значение m1n и заполняет таблицу T по строкам сверху вниз:
for := 1 to n do m[ii] := 0; {заполнение первой строки}

for := 1 to n –1 do

for := 1 to n – l do

begin

j := i + l;

{заполнение T(ij):}

m[ij] := +;

for := i to j – 1 do

begin

s := m[ik] + m [k +1,j] + r1 * rk * rj;

if s  m[ijthen 

begin m[ij] := s;

q[ij] := k

end { if }

end { for k }

end { for i }
Этот алгоритм требует для хранения таблицы примерно n2/2 элементов памяти и около n3/3 выполнений тела внутреннего цикла.

Рассмотрим работу алгоритма для ранее приведенного примера вычисления M1  M2  M3  M4 (размеры матриц, как указано ранее). Для заполнения строки таблицы при l = 1 вычислим последовательно

m1,2 = m1,1 + m2,2 + r0  r1  r2= 102050=10000

m2,3 = m2,2 + m3,3 + r1  r2 r3= 20501=1000

m3,4 = m3,3 + m4,4 + r2  r3 r4= 501100=5000

Здесь фактически минимум находить не требуется, т. к. тело цикла по k выполняется лишь один раз (при k = i). Заполненная строка таблицы есть


l = 1

m1,2 = 10000

q1,2 = 1

m2,3 = 1000

q2,3 = 2

m3,4 = 5000

q3,4 = 3


Далее для заполнения строки таблицы при l = 2 вычислим последовательно

m1,3 = Min {m1k + mk +1,3 + r0  rk  r3  = 1, 2} =

Min {m1,1 + m2,3 + r0  r1  r3 , m1,2 + m3,3 + r0  r2  r3} =

Min {0 + 1000 + 200, 10000 + 0 + 500} =

 Min{1200, 10500} = 1200 (при k = 1),

m2,4 = Min {m2k + mk +1,4 + r1 rk  r4 = 2, 3} =

Min {m2,2 + m3,4 + r1  r2  r4 , m2,3 + m4,4 + r0  r2  r3} =

Min {0 + 5000 + 100000, 1000 + 0 + 2000} =

 Min{105000, 3000} = 3000 (при k = 3),

и дополним таблицу следующей строкой:


l = 1

m1,2 = 10000

q1,2 = 1

m2,3 = 1000

q2,3 = 2

m3,4 = 5000

q3,4 = 3

l = 2

m1,3 = 1200

q1,3 = 1

m2,4 = 3000

q2,4 = 3





Наконец, вычислим последнюю строку таблицы, состоящую из одной ячейки Т(1, 4):

m1,4 = Min { m1k + mk +1,4 + r0  rk  r4= 1, 2, 3} =

 Min { m1,1 + m2,4 + r0  r1  r4, m1,2 + m3,4 + r0  r2  r4,

m1,3 + m4,4 + r0  r3  r4, } =

 Min {0 + 3000 + 20000, 10000 + 5000 + 50000, 1200 + 0 + 1000} =

 Min {23000, 65000, 2200} = 2200 (при k = 3).

Итак, вся таблица вычислена и имеет вид



l = 0

m1,1 = 0

q1,1 = 1

m2,2 = 0

q2,2 = 2

m3,3 = 0

q3,3 = 3

m4,4 = 0

q4,4 = 4

l = 1

m1,2 = 10000

q1,2 = 1

m2,3 = 1000

q2,3 = 2

m3,4 = 5000

q3,4 = 3




l = 2

m1,3 = 1200

q1,3 = 1

m2,4 = 3000

q2,4 = 3




l = 3

m1,4 = 2200

q1,4 = 3





Пока мы вычислили лишь оптимальное количество требуемых умножений m1,4 = 2200 и записали в таблицу дополнительные данные qij, позволяющие получить собственно порядок перемножения матриц. В рассмотренном примере этот порядок можно получить, начиная от финальной ячейки и продвигаясь по закрашенным ячейкам. Действительно, поскольку q1,4 = 3, то минимум был получен при m1,3 + m4,4 + r0  r3  r4. Это значит, что последним по порядку должно производиться умножение матриц M(1, 3)  M4. В свою очередь, поскольку q1,3 = 1, то на предыдущем шаге минимум был получен при m1,1 + m2,3 + r0  r1  r3, т. е. матрица M(1, 3) должна вычисляться как M(1, 3) = M1  M(2, 3), а M(2, 3) = M2  M3. Это в итоге дает оптимальный порядок перемножения матриц (M1  (M2  M3))  M4.

В общем случае порядок перемножений матриц легко определить рекурсивно. Пусть имеется функция перемножения двух матриц func Mult ABMatrix): Matrix. Тогда «набросок» функции перемножения цепочки матриц выглядит так

func MatrixSeqMult ijIndex): Matrix;

{i  j}

global q: Tab_q;

var k: Index; var ABMatrix;

begin

if i  j then

begin

k := q[ij];

A := MatrixSeqMult ik);

B := MatrixSeqMult k +1, j);

Return Mult(AB)

end

else {i = j} Return Mi

end {MatrixSeqMult}

Доступ к матрицам Mi заданной цепочки M1  M2  ...  Mn здесь не детализирован.
Полезно сравнить решение, полученное методом динамического программирования, с решением методом ветвей и границ. В рассмотренном примере возможны следующие 5 вариантов перемножения матриц M1  M2  M3  M4, а именно:

M1  (M2  (M3  M4)),

M1  ((M2  M3)  M4),

(M1  M2)  (M3  M4),

(M1  (M2  M3))  M4,

((M1  M2)  M3)  M4.

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

M
(1,4)

M1  M(2,4) M(1,2)  M(3,4) M(1,3)  M4




M2  M(3,4) M(2,3)  M4 M1  M2  M3  M4 M1  M(2,3) M(1,2)  M3

M3  M4 M2  M3  M2  M3  M1  M2 
Оценку количества узлов дерева в общем случае можно получить, подсчитав все возможные варианты расстановок скобок в произведении матриц. Пусть pn – число вариантов расстановок скобок в произведении n сомножителей (считая самые внешние скобки). Считая, что «последнее» по порядку умножение может оказаться на любом из n –1 мест, запишем следующее рекуррентное соотношение

pn = p1 pn –1 + p2 pn –2 + … + pn –2 p2 + pn –1 p1.

Начальным условием является p1 = 1. Далее p2 = p1 p1 = 1, p3 = p1 p2 + p2 p1 =2, p4p1 p3 + p2 p2 + p3 p1 = 4. Оказывается, что решением этого рекуррентного уравнения являются так называемые числа Каталана pn = Сn –1, где Сn =(2 k | k) / (k +1), а запись (n | m) обозначает биномиальный коэффициент (n | m) = n!/(m! (n – m)!). При больших значениях n справедливо Сn  4n / (n sqrt( n)), т. е. число узлов в дереве перебора есть экспоненциальная функция от n.

Приведем несколько первых чисел Каталана

n

0

1

2

3

4

5

6

7

8

9

10

Cn

1

1

2

5

14

42

132

429

1430

4862

16796