
- •Овсянник в.Н. Лабораторные работы по курсу «Объектно-ориентированное программирование»
- •13. Разработка приложения с архитектурой «документ-вид». Часть 2 120
- •14. Разработка приложения с архитектурой «документ-вид». Часть 3 135
- •1.Разработка типового консольного приложения
- •1.1.Методические указания
- •1. Запуск и настройка ис mvs-2008.
- •2.Поиск данных в массиве
- •3.Обработка текстового файла
- •4.Задача «куча камней»
- •5.Реализация алгоритма полного перебора
- •6. Исследование погрешностей вычислений
- •7.Поиск экстремумов с ограничениями или «Брачное агенство»
- •Постановка задачи
- •Задание
- •Листинг файла mAgency.Cpp (с главной функцией)
- •Листинг файла Lib.H
- •Листинг файла Lib.Cpp
- •8.Приложение с окном вида
- •9.Разработка графического редактора
- •Задание.
- •9.1.Проектирование программы
- •9.2.Разработка интерфейса
- •Установка флагов
- •Создание меню и панели инструментов
- •Обработка сообщений о нажатии кнопки мыши
- •9.3.Рисование
- •9.4.Растягивание фигур
- •9.5.Обновление изображения
- •9.6.Сохранение метафайла на диске и его загрузка
- •10.Приложение, основанное на модальном диалоговом окне
- •Методические указания Модальные и немодальные диалоговые окна
- •Ресурсы и элементы управления
- •Сценарий создания приложения
- •Разбор приложения
- •Усовершенствование приложения
- •11.Приложение с контекстным меню и строкой состояния
- •11.1.Методические указания к первой части работы
- •11.2.Сценарий выполнения первой части работы
- •11.3.Методические указания ко второй части работы Строка состояния
- •Определение секций в строке состояния
- •Строка сообщений
- •Индикатор состояния
- •Управление строкой состояния
- •11.4.Сценарий выполнения второй части работы
- •12.Разработка приложения с архитектурой «документ-вид». Часть 1
- •12.1.Сценарий создания приложения
- •13.Разработка приложения с архитектурой «документ-вид». Часть 2
- •13.1.Методические указания Класс коллекций cObList
- •13.2.Сценарий выполнения работы
- •14.Разработка приложения с архитектурой «документ-вид». Часть 3
- •14.1.Методические указания
- •15.Класс вектор
- •15.1.Пример класса tVector
- •15.2.Класс tVector с перегруженными операциями
- •16.Приложение с таблицей
- •16.1.Вариант 1 Сценарий выполнения работы
- •16.2.Вариант 2 Сценарий выполнения работы
5.Реализация алгоритма полного перебора
Любая найденная в программе ошибка – не последняя
Закон Мерфи
Цель работы – научиться реализовать алгоритм решения оптимизационной «задачи о камнях» методом полного перебора (4 час. на 1 студента, 2час. на бригаду из двух студентов, 1час. на бригаду из четырех и т.д.).
Постановка задачи.
Сущность любой оптимизационной задачи сводится к тому, что вы должны отыскать такое наилучшее (лысоголовые говорят «оптимальное») сочетание варьируемых параметров (т.е. тех, которые вы можете изменять), которое бы соответствовало наилучшему решению, т.е. экстремальному значению некоторой целевой функции. Вот живой пример из (студенческой) жизни. Вы иногородний, живете в общежитии или «на уголке» и у вас есть счастливая возможность один раз в неделю (в две недели, в месяц …) приехать домой к родителям и набрать рюкзак продуктов весом до 20 (10 или 30 или …) кг. Какие же продукты следует взять, если, конечно, у вас есть выбор? Если исходить только из энергетической ценности продуктов, то, например, выгоднее всего взять 20 кг сала, или шоколада или сала в шоколаде и т.д. Очевидно, чтобы, как говорится, «не слиплось», надо взять все-таки разные продукты: сало, картофель, те же огурцы и т.д. и др. вкусненькое и полезное. Так что же взять при наличии ограничения в весе рюкзака? Чтобы решить эту проблему, вы и должны составить (придумать, написать) так называемую целевую функцию (произносится как «хвункція»). Даже в данном съедобном случае она будет выглядеть достаточно сложной, так как вам предстоит для каждого из кандидатов на попадание в ваш рюкзак задать некоторые коэффициенты, обычно называемые «весовыми» теми же лысоголовыми:
количество удовольствия на кг веса;
степень обязательности наличия в рационе (хоть огурцы и не очень калорийны, но они ведь должны быть в рационе!);
энергетическая ценность в тех же ККал;
стоимость в грв. и т.д. и т.п.
Ну, в целом, вы и так понимаете сущность, сложность и, главное, ценность оптимального решения этой жизненно важной задачи.
Ну а при чем же здесь «задача о камнях», вопросит, как говорят писатели, «внимательный читатель»? А очень просто: у вас нет рюкзака, а есть две сумки и две (соответственно?), руки, и вам требуется распределить продукты по двум сумкам так, чтобы разность их веса была минимальной, так как в противном случае у вас будет искривление позвоночника (сколиоз по-научному). Если всего вам удалось добыть «у предков» 20 видов харчей и вы захотите путем прямого перебора на практике (т.е. путем загрузки сумок и их последующего взвешивания) найти наилучший вариант распределения снеди по двум сумкам, то вам придется в общем случае перебрать около 220 вариантов, а это примерно 1 млн. Успеете до отправления электрички, еще в этой жизни?
Замечание. Если вы и ваши родители живут в Харькове, то не думайте, что вам не надо выполнять эту лабу. Для того чтобы попасть в универ вовремя и с минимальными потерями денежных средств, времени и нервов (или чтобы еще и поспать во время поездки или, не приведи господи такому присниться, выполнить домашнее задание) вам предстоит из множества вариантов маршрутов городского транспорта с учетом стоимости проезда, времени в пути, интервалов движения, вероятности занять сидячее место и др. значимых для вас факторов выбрать оптимальный маршрут. Короче говоря – вы тоже должны делать эту лабу.
Бесценные методические указания.
Для того чтобы перебрать все возможные варианты разделения камней на две кучи и выбрать оптимальный, надо каким-то образом их генерировать. Допустим, у нас есть 8 камней. Тогда введем целочисленный массив Stones из 8 элементов и будем в него записывать 1 и 0: 1 будет указывать на принадлежность камня к первой куче, а 0 – соответственно ко второй (или наоборот – все равно). Тогда, если мы переберем все возможные сочетания 1 и 0, то мы таким образом рассмотрим и все возможные варианты разделения камней на две кучи. Но как реализовать алгоритм генерирования этих всевозможных сочетаний 1 и 0? Шерлок Холмс сказал бы так: «Элементарно, Ватсон!».
Давайте возьмем один единственный байт Byte и будем трактовать значения его бит (а это 1 или 0) как принадлежность камня к одной или другой куче. Очевидно, нам не подходит случай, когда все биты одинаковы: равны 0 или 1. Будем присваивать байту последовательно значения 1, 2, 3 и т.д., т.е. будем просто для получения нового варианта разделения камней просто прибавлять к байту значение 1:
-
Значения бит
Значение байта Byte
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
1
0
2
0
0
0
0
0
0
1
1
3
0
0
0
0
0
1
0
0
4
0
0
0
0
0
1
0
1
5
…
1
1
1
1
1
1
1
0
254
Теперь уже можно поступить таким образом: проверять значения бит байта Byte и, соответственно, присваивать 0 и 1 элементам массива Stones. Теперь, анализируя значения элементов массива Stones, можно подсчитать вес одной и второй кучи камней, найти их разность, сравнить ее с предыдущим вариантом и запомнить как лучшую или отвергнуть.
Кстати, вы заметили, что значение байта 254 дает тот же вариант разделения камней на две кучи, что и значение 1? Может быть это не единственная «накладка» и можно сократить число рассматриваемых вариантов?
Совсем нетрудно догадаться, что если камней не 8, а больше, то надо взять не один байт, а два, четыре или 8 (тип __int64). Если и этого мало, то придется взять массив байтов и несколько усложнить алгоритм.
В качестве подсказки посмотрите на приведенный ниже текст функции PrintVariants, которая генерирует варианты разделения камней на две кучи и выводит их для частного случая 8 камней. Если запустить эту функцию на выполнение, то она выведет 255 вариантов разделения камней на две кучи.
|
Задание.
Во-первых, постарайтесь понять, чем закомментированный вариант PrintVariants отличается от реализованного.
Во-вторых, проанализируйте, не генерирует ли функция повторяющихся вариантов.
В-третьих, как надо усовершенствовать функцию, чтобы она работала не только для случая 8 камней, но и для случаев меньшего и большего числа камней?
Разработайте алгоритм и программу, которая бы позволяла решать задачу о камнях путем полного перебора вариантов разделения камней.
Разработайте тесты, которые бы позволили доказать работоспособность вашей программы. Для сокращения времени тестирования рекомендую задать веса камней в виде массивов и по очереди их подставлять в программу.
Каждая бригада должна реализовать программу для своего максимально возможного числа камней, заданного в приведенной ниже таблице, но при этом программа должна корректно работать и при меньшем числе камней.
Варианты заданий
-
Номер компьютера
Максимальное число камней
1
19
2
15
3
11
4
27
5
31
6
13
7
29
8
30
9
17
10
9
11
18
12
24