Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lektsii_TRPO / 5_LessPerebor.doc
Скачиваний:
54
Добавлен:
12.03.2015
Размер:
73.22 Кб
Скачать

9

Переборные задачи

На практике неоднократно встречаются задачи, где требуется обработать (пере­брать) все элементы некоторого конечного множества. В простейших слу­чаях элемент множества можно представить числом. При­мер такой задачи — по­иск за­данного числа в одномерном массиве. Здесь для указа­ния элемента массива доста­точно задать его индекс. Более слож­ные случаи, когда элементы интересую­щего нас множества сами имеют некото­рую структуру. (Именно такие задачи обычно относят к переборным.) Во многих случаях элементы множества естест­венно запи­сывать в виде последовательно­сти чисел фиксированного или перемен­ного раз­мера. Очень многие переборные задачи можно свести к перебору последова­тельно­стей. В некоторых задачах (см. например, задачу о коммивоя­жере в главе 1) требу­ется генерировать последовательности путем всевозмож­ных перестановок компо­нент некоторой заданной последовательности фиксирован­ной длины. Пра­вила генерации последовательностей могут меняться в за­висимости от задачи: слу­чайным образом, в лексикографическом порядке, пу­тем различных сочетаний ком­понент и т. п. Примером такой задачи (в действительно­сти она эквивалентна задаче пере­бора последовательностей) явля­ется задача прохождения (обхода) деревьев. Де­рево — это граф без циклов, в кото­ром выделена одна вершина, называемая кор­нем. Для каждой вершины де­рева существует единственный путь в нее из корня. Задача состоит в том, чтобы «обойти» все вершины дерева. Если перенуме­ровать все ребра, выходящие из каж­дой вершины, то путь из корня, однозначно со­поставляе­мый каждой вершине, можно будет в свою очередь задать с помощью по­следовательности номеров проходи­мых ребер. Лексикографический порядок пере­бора последовательностей отвечает способу прохождения дерева, известному как перебор в глубину. Нахо­дясь в какой-либо вершине, мы сначала пытаемся пойти «в глубину», т. е. уда­литься от корня; если это невозможно, то мы возвраща­емся назад и пытаемся пойти в глубину по следующему ребру.

Многие практические задачи сводятся к отысканию минимума (максимума) некоторой функции на множестве. Искомым элементом множества часто является функция от времени (например, ищется закон управления самолетом, обеспечиваю­щий наибыстрейшее достижение заданной высоты и скорости). Эту функцию ап­проксимируют последователь­ностью ее значений в дискретные мо­менты времени, получая задачу поиска минимума в множестве последовательно­стей. Можно осу­ществить поиск минимума путем полного перебора всех допусти­мых последова­тельностей. Метод динамического программирования позво­ляет в ряде случаев со­кратить перебор. Рассмот­рим несколько типичных примеров генерации последова­тельностей и работы с ними при решении переборных задач.

7.1. Полный перебор.

Для решения переборных задач обычно используются разновидности следую­щей схемы программы:

Схема 1

Var x :элемент множества;

x := первый элемент;

обработать x; While x<> последний элемент Do Begin x: =следующий за x;

обработать x;

End;

Иногда удается добавить к множеству еще один, фиктивный элемент, не подле­жащий обработке, который располагается перед первым обрабатываемым элементом, либо вслед за последним В этом случае обработку первого элемента можно выполнить наряду со всеми в цикле:

Схема 2 Схема 3

x:=фиктивный элемент; x:=первый элемент;

Repeat Repeat

x:=следующий за x; обработать x;

обработать x; x:=следующий за x;

Until x = последний элемент; Until x = фиктивный элемент;

Для конкретизации этих схем необходимо ответить на два вопроса.

1.Как будут записываться в программе элементы множества (тип элемент множества)?

2. В каком порядке мы будем перебирать их (инструкция x:=следующий за x;)?

Рассмотрим пример. Подсчитать число счастливых билетов, т. е. таких набо­ров из шести цифр А,B,C,D,E,F, что A+B+C=D+E+F. Будем ре­шать задачу путем перебора всех комбинаций из шести цифр (это решение далеко не самое эффек­тив­ное). Таким образом, элемент множества задается последова­тель­но из шести цифр, каждая из которых принимает значения от 0 до 9. Для хране­ния этой последова­тельности используем шесть отдельных переменных. В данном случае можно, не следуя буквально введенным выше схемам, организо­вать перебор с помо­щью шести вложенных циклов FOR:

Program Happy_Ticket ;

Var A,B,C,D,E,F,k :Integer; { k – число найденных счастливых билетов}

Begin

k:=0;

For A:=0 To 9 Do

For B:=0 To 9 Do

For C:=0 To 9 Do

For D:=0 To 9 Do

For E:=0 To 9 Do

For F:=0 To 9 Do

If A+B+C = D+E+F Then k:=k+1;

Writeln(‘ЧИСЛО СЧАСТЛИВЫХ БИЛЕТОВ=’,k);

End.

Кстати сказать, счастливых билетов 55252 (если считать и 000000), что состав­ляет примерно 1/18 общего числа билетов.

Соседние файлы в папке Lektsii_TRPO