Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
АиПА / Лекции / 6_Комбинаторные задачи и вычисл на множествах.doc
Скачиваний:
16
Добавлен:
07.02.2016
Размер:
150.53 Кб
Скачать

7. Поиск наибольшей монотонно возрастающей подпоследовательности

Рассмотрим вначале более простую формулировку задачи: требуется найти длину наибольшей монотонно возрастающей подпоследовательности (а не саму подпоследовательность).

Алгоритм 1: перебор подпоследовательностей

Пусть задана упорядоченная последовательность чисел: A = <a0, a1, ... , an-1>. Подпоследовательностью из А называют последовательность, которую можно получить из А путем удаления из нее некоторого множества элементов. Задача состоит в том, чтобы найти длину наибольшей монотонно возрастающей подпоследовательности, которая содержится в А.

Самая простая идея состоит в том, чтобы алгоритм решения задачи построить на основе полного перебора всех подпоследовательностей.

Реализация

Любую подпоследовательность из А можно представить, указав множество номеров элементов последовательности А, включаемых в подпоследовательность. Создадим массив q[n] и присвоим его элементам значения 0,1,2, ... , n-1. Будем считать эти числа множеством и будем перебирать все подмножества из него. Для каждого подмножества будем проверять монотонность соответствующей подпоследовательности и фиксировать ее длину.

Для перебора всех подмножеств из множества q можно использовать следующую функцию из syst.h:

Int subsetnext(int n, int r, int* q)

Здесь r – размер выбираемого подмножества. Функция возвращает номер очередного подмножества. Если все подмножества уже исчерпаны, функция возврашает 0.

Оценка эффективности алгоритма

Общее количество подпоследовательностей будет равно числу всех подмножеств из n-элементного множества. Это число равно 2n . Если с - это наибольшее время, которое требуется для проверки одной подпоследовательности, то для времени работы нашего алгоритма будем иметь:

.

Время работы алгоритма в среднем равно:

t = Const2n .

Результаты испытания алгоритма.

Исходная последовательность  случайные числа из интервала [0, 999]. Длина исходной последовательности: 150 000. Время выполнения: .

Алгоритм 2: метод рейтинга

Рассмотрим более эффективный алгоритм, который реализует так называемый метод рейтинга. Пусть

A = <a1, a2, ..., an >

исходная последовательность. Свяжем с каждым элементом последовательности ai целое число - рейтинг pi . Всем рейтингам вначале присвоим единичные значения. Рассмотрим следующую процедуру:

for i: =1 to n-1

for j: = i+1 tо n

if aj > ai and pj < pi+1 then pj : = pi+1

Можно убедиться, что после выполнения последней процедуры наибольший из рейтингов будет равен искомой величине  длине наибольшей монотонно возрастающей последовательности. Ниже показано состояние массива рейтингов p для каждого шага i процедуры (1). Длина исходной последовательности  10, исходная последовательность A = < 7, 3, 5, 4, 8, 0, 5, 6, 2, 9 > .

| ------------------------------------

| 7 3 5 4 8 0 5 6 2 9

| ------------------------------------

1 | 1 1 1 1 2 1 1 1 1 2

2 | 1 1 2 2 2 1 2 2 1 2

3 | 1 1 2 2 3 1 2 3 1 3

4 | 1 1 2 2 3 1 3 3 1 3

5 | 1 1 2 2 3 1 3 3 1 4

6 | 1 1 2 2 3 1 3 3 2 4

7 | 1 1 2 2 3 1 3 4 2 4

8 | 1 1 2 2 3 1 3 4 2 5

9 | 1 1 2 2 3 1 3 4 2 5

10 | 1 1 2 2 3 1 3 4 2 5

В первой строке указан исходный массив, в левой колонке - номер шага. Красным цветом отмечены элементы массива рейтингов, подвергаемых проверке на текущем шаге. Решением задачи является число L = 5.

Ниже приведена реализация алгоритма решения задачи в виде функции С++.