If (включение приемлемо)
{ включение i-го объекта; if (i < n) Try(i+1); else проверка оптимальности;
исключение i-го объекта;
}
If (приемлемо невключение )
{ if (i < n) Try(i+1); else проверка оптимальности;
}
}
34)Задача о лабиринте Пометить числом 1 и
поместить входную клетку в
очередь.
Взять из очереди клетку.
Если это выходная клетка, то
перейти на шаг 4, иначе
пометить все непомеченные
соседние клетки числом ,
на 1 большим, чем данная,
и поместить их в очередь.
Если очередь пуста, то выдать
«Выхода нет» и выйти, иначе
перейти на шаг 2.
Обратный ход:
начиная с выходной клетки,
каждый раз смещаться на
клетку, помеченную на 1
меньше, чем текущая, пока не
дойдем до входной клетки.
При проходе выделять
пройденные клетки.
37) Слово «программирование» в словосочетании «динамическое программирование» в действительности к традиционному программированию почти никакого отношения не имеет и происходит от словосочетания «математическое программирование», которое является синонимом слова «оптимизация». Поэтому слово «программа» в данном контексте скорее означает оптимальную последовательность действий для получения решения задачи. К примеру, определенное расписание событий на выставке иногда называют программой. Программа в данном случае понимается как допустимая последовательность событий.
В общем случае мы можем решить задачу, в которой присутствует оптимальная подструктура, проделывая следующие три шага.
Разбиение задачи на подзадачи меньшего размера.
Нахождение оптимального решения подзадач рекурсивно, проделывая такой же трехшаговый алгоритм.
Использование полученного решения подзадач для конструирования решения исходной задачи.
Рассмотрим произвольную последовательность целых чисел. Можно поставить знаки операций + или – между целыми в данной последовательности, получая при этом различные арифметические выражения, которые при их вычислении имеют различные значения. Давайте, например, возьмем следующую последовательность: 17, 5, -21, 15. Из нее можно получить восемь различных выражений:
17+5+-21+15= 16 17-5+-21+15=6
17+5+-21-15=-14 17+5--21+15=58
17+5--21-15= 28 17-5+-21-15=-24
17-5--21+15= 48 17-5--21-15=18
Назовем последовательность делимой на K, если можно так расставить операции + или – между целыми в последовательности, что значение полученного выражения делилось бы нацело на K. В приведенном выше примере последовательность делима на 7 (17+5+-21-15=-14), но не делима на 5.
Напишите программу, которая определяет делимость последовательности целых чисел.
Если число N делится на некоторое число К, то остаток от деления N на K равен 0.
Остаток от деления суммы чисел на некоторое число равен остатку от деления суммы остатков от деления каждого числа на это число.
(a + b) mod c == (a mod c + b mod c ) mod c
Ganaster
первая строка входного файла содержит значения N, K и T, разделенные пробелами (1 £ N £ 100, 1 £ K £ 100, 0 £ T £ 30000 ); вторая строка содержит моменты времени, в которые гангстеры подходят к ресторану T1, T2, ... , TN, разделенные пробелами (0 £ Ti £ T для i = 1, 2. ..., N);в третьей строке записаны суммы денег каждого гангстера P1, P2, ... , PN, разделенные пробелами ( 0 £ Pi £ 300, для i = 1, 2. ..., N); четвертая строка содержит значения ширины плеч каждого гангстера, разделенные пробелами (0 £ Si £ K для i = 1, 2. ..., N). Все значения целые.
Выходные данные: В выходной файл выдать одно целое число — максимальное значение достатка всех гангстеров, собранных в ресторане. Если ни один гангстер не может попасть в ресторан, выдать 0.
Пример 1 Пример 2
Вход: Выход: Вход: Выход:
4 10 20 26 2 17 100 0
10 16 8 16 5 0
10 11 15 1 50 33
10 7 1 8 6 1
38 )Типы данных Типы данных бывают следующие:
Простые.
Перечисляемый тип. Может хранить только те значения, которые прямо указаны в его описании.
Числовые. Хранятся числа. Могут применяться обычные арифметические операции.
Целочисленные: со знаком, то есть могут принимать как положительные, так и отрицательные значения; и без знака, то есть могут принимать только неотрицательные значения.
Вещественные: с запятой (то есть хранятся знак и цифры целой и дробной частей) и с плавающей запятой (то есть число приводится к виду m*be, где m — мантисса, b — основание показательной функции, e — показатель степени (порядок) (в англоязычной литературе экспонента), причём в нормальной форме 0<=m<b, а в нормализованной форме 1<=m<b, e — целое число и хранятся знак и числа m и e).
Числа произвольной точности, обращение с которыми происходит посредством длинной арифметики. Примером языка с встроенной поддержкой таких типов являетсяUBASIC, часто применяемый среди криптографов.
Символьный тип. Хранит один символ. Могут использоваться различные кодировки.
Логический тип. Имеет два значения: истина и ложь, при троичной логике может иметь и третье значение — «не определено» (или «неизвестно»). Могут применяться логические операции. Используется в операторах ветвления и циклах. В некоторых языках является подтипом числового типа, при этом ложь=0, истина=1.
Множество. В основном совпадает с обычным математическим понятием множества. Допустимы стандартные операции с множествами и проверка на принадлежность элемента множеству. В некоторых языках рассматривается как составной тип.
Составные (сложные).
Массив. Является индексированным набором элементов одного типа. Одномерный массив — вектор, двумерный массив — матрица.
Строковый тип. Хранит строку символов. Аналогом сложения в строковой алгебре является конкатенация (прибавление одной строки в конец другой строки). В языках, близких к бинарному представлению данных, чаще рассматривается как массив символов, в языках более высокой абстракции зачастую выделяется в качестве простого.
Запись (структура). Набор различных элементов (полей записи), хранимый как единое целое. Возможен доступ к отдельным полям записи. Например, struct в C или record в Pascal.
Файловый тип. Хранит только однотипные значения, доступ к которым осуществляется только последовательно (файл с произвольным доступом, включённый в некоторые системы программирования, фактически является неявным массивом).
Класс.
Другие типы данных. Если описанные выше типы данных представляли какие-либо объекты реального мира, то рассматриваемые здесь типы данных представляют объекты компьютерного мира, то есть являются исключительно компьютерными терминами.
Указатель. Хранит адрес в памяти компьютера, указывающий на какую-либо информацию, как правило — указатель на переменную.
Ссылка.
39) Все данные, используемые в программе, можно разделить на две группы: константы и переменные. К первой группе относятся данные, не изменяющие своего значения в ходе выполнения программы, данные второй группы могут изменять свое значение.
Как константы, так и переменные могут быть различных типов, которые определяют их структуру, набор допустимых значений, правила использования и способ представления в ЭВМ. Иерархию типов данных можно представить следующей схемой.
Простые (скалярные) типы:
целые,
вещественные,
символьные,
указатели,
перечислимый тип.
Составные (структурированные) типы:
массив,
структура,
объединение.
Переменная простого (скалярного) типа в любой момент времени хранит только одно значение. В отличие от простых переменных, переменные составного (структурированного) типа одновременно хранят несколько значений.
Целые и вещественные переменные предназначены для хранения чисел, символьные переменные – это также числовые переменные, они хранят ASCII коды символов.
Указатель – это переменная, значением которой является адрес объекта (обычно другой переменной) в памяти компьютера. Таким образом, если одна переменная содержит адрес другой переменной, то говорят, что первая переменная указывает (ссылается) на вторую.
Массив – это группа элементов одинакового типа (double, float, int и т. п.). Из объявления массива компилятор должен получить информацию о типе элементов массива и их количестве.
Структура – это совокупность элементов, объединенных под одним именем. Структура представляет собой составной объект, в который могут входить элементы различных типов. Для каждого элемента выделяется своя область памяти.
Перечислимый тип представляет собой набор целочисленных констант, используемых обычно для организаций разветвлений в программе.
Объединение – это совокупность переменных различных типов, использующих одну и ту же область памяти. Объединение подобно структуре, однако в каждый момент времени объединение может хранить значение только одного из элементов объединения. Хотя доступ к этой области памяти возможен с использованием любого из элементов, элемент для этой цели должен выбираться так, чтобы полученный результат не был бессмысленным
40)Область видимости самого класса по-разному определяется в разных языках программирования. В одних языках (таких как Delphi) все классы имеют глобальную видимость (с учётом видимости модуля), в других (таких как Java) область видимости класса связана с содержащей его единицей компиляции (в Java — с пакетом), в третьих (таких как C++ и C#) область видимости класса определяется пространствами имён (namespaces), которые задаются программистом явно и могут совпадать или не совпадать с единицами компиляции. Когда компилятор встречает имя x внутри функции someFunc, он смотрит, определено ли что-то с таким именем в локальной области видимости. Если да, то объемлющие области видимости не просматриваются. В данном случае имя x в функции someFunc принадлежит переменной типа double, а глобальная переменная с тем же именем x имеет тип int, но это несущественно. Правила сокрытия имен в C++ предназначены для одной-единственной цели: скрывать имена. Относятся ли одинаковые имена к объектам одного или разных типов, не имеет значения. В нашем примере переменная x типа double скрывает переменную x типа int.
40) Процедуры и функции представляют собой относительно самостоятельные фрагменты программы, оформленные особым образом и снабженные именем. Упоминание этого имени в тексте программы называется вызовом процедуры (функции). Отличие функции от процедуры заключается в том, что результатом исполнения операторов, образующих тело функции, всегда является некоторое значение, поэтому обращение к функции можно использовать в соответствующих выражениях наряду с переменными и константами. Условимся далее называть процедуру или функцию общим именем “подпрограмма”, если только для излагаемого материала указанное отличие не имеет значения. ЛОКАЛИЗАЦИЯ ИМЕН
Описать подпрограмму - значит указать ее заголовок и тело. В заголовке объявляются имя подпрограммы и формальные параметры, если они есть. Для функции, кроме того, указывается тип возвращаемого ею результата. За заголовком следует тело подпрограммы, которое подобно программе состоит из раздела описаний и раздела исполняемых операторов. В разделе описаний подпрограммы могут встретиться описания подпрограмм низшего уровня, а в них - описания других подпрограмм и т. д.
Подпрограмма – это обособленный участок кода, который решает одну небольшую задачу. Подпрограммы как раз и являются результатом декомпозиции основной большой задачи. Код подпрограммы располагается либо в отдельном файле (модуле), либо в начале кода основной программы. Из текста программы доступ к коду функции или процедуры осуществляется путем вызова их по имени. Вызов происходит в том месте программы, где следует использовать код данной функции.
Структурное программирование делает программу более понятной. Ее легче отлаживать и сопровождать. Разные модули (в которых содержатся функции и процедуры) могут разрабатывать разные люди, в результате чего проще организовать коллективное решение одной большой задачи, т.к. каждый будет решать свою подзадачу.
42) Файлом называют способ хранения информации на физическом устройстве. Файл — это понятие, которое применимо ко всему — от файла на диске до терминала.
В C++ отсутствуют операторы для работы с файлами. Все необходимые действия выполняются с помощью функций, включенных в стандартную библиотеку. Они позволяют работать с различными устройствами, такими, как диски, принтер, коммуникационные каналы и т.д. Эти устройства сильно отличаются друг от друга. Однако файловая система преобразует их в единое абстрактное логическое устройство, называемое потоком.
Текстовый поток — это последовательность символов. При передаче символов из потока на экран, часть из них не выводится (например, символ возврата каретки, перевода строки).
Двоичный поток — это последовательность байтов, которые однозначно соответствуют тому, что находится на внешнем устройстве.
Организация работы с файлами средствами C
Объявление файла
FILE *идентификатор;
Пример
FILE *f;
Открытие файла:
fopen(имя физического файла, режим доступа)
Режим доступа — строка, указывающая режим открытия файла файла и тип файла
Типы файла: бинарный (b); текстовый (t)
Значение |
Описание |
r |
Файл открывается только для чтения |
w |
Файл открывается только для записи. Если соответствующий физический файл существует, он будет перезаписан |
a |
Файл открывается для записи в конец (для дозаписи) или создается, если не существует |
r+ |
Файл открывается для чтения и записи. |
w+ |
Файл открывается для записи и чтения. Если соответствующий физический файл существует, он будет перезаписан |
a+ |
Файл открывается для записи в конец (для дозаписи) или создается, если не существует |
Например
f = fopen(s, "wb");
k = fopen("h:\ex.dat", "rb");
43) Виды операторов цикла в языке программирования Си.
Оператор цикла while
Описание: while (выражение) оператор;
Действие:
Выполняется оператор до тех пор, пока значение выражения в скобках истинно. Проверка значения выражения происходит перед каждым выполнением оператора. Когда значение выражения ложно, цикл while заканчивается. Если выражение ложно с самого начала, оператор не выполняется ни разу.
Комментарий:
Следует заметить, что после ключевого слова while и выражения, заключенного в круглые скобки, точка с запятой не ставится.
Оператор иногда называется телом цикла. В теле цикла должны выполняться действия, в результате которых меняется значение управляющего выражения. В противном случае можем получить бесконечный цикл.
.
Оператор цикла for
Описание: for (выражение 1; выражение 2; выражение 3) оператор;
Действие:
В круглых скобках содержится три выражения. Первое из них служит для инициализации счетчика. Она осуществляется только один раз – когда цикл for начинает выполняться. Второе выражение необходимо для проверки условия, которая осуществляется перед каждым возможным выполнением тела цикла. Когда выражение становится ложным, цикл завершается. Третье выражение вычисляется в конце каждого выполнения тела цикла, происходит приращение числа на шаг.
Комментарий: в операторе цикла for точка с запятой после закрывающейся круглой скобки не ставится. Любое из трех или все три выражения в операторе могут отсутствовать, однако разделяющие их точки с запятыми опускать нельзя. Если отсутствует выражение 2, имеем бесконечный цикл. Например:for (scanf("%d",&p);;p++) оператор;
В языке СИ предусмотрены две нетрадиционные операции: (++) – для увеличения на единицу и (--) – для уменьшения на единицу значения операнда. Операции ++ и -- можно записывать как перед операндом, так и после него. В первом случае (++n или --n) значение операнда (n) изменяется перед его использованием в соответствующем выражении, а во втором (n++ или n--) – после его использования.
Если отсутствуют выражения 1 и 3, цикл становится эквивалентным while. Например:for (;a<20;) оператор;
Каждое из выражений может состоять из нескольких выражений, объединенных операцией "запятая". Например: for(i=0, j=1; i<100; i++, j++) a[i]=b[j];
Тело цикла заключается в фигурные скобки, если в нем более одного оператора.
44) Представление массивов и структур в памяти ЭВМ. Вычисление адресов элементов
Некоторые структуры: Массив (функция с конечной областью определения) - простая совокупность элементов данных одного типа, средство оперирования группой данных одного типа. Отдельный элемент массива задается индексом. Массив может быть одномерным, двумерным и т.д. Разновидностями одномерных массивов переменной длины являются структуры типа кольцо, стек, очередь и двухсторонняя очередь. Если массив всегда занимает непрерывный участок памяти, то список являет¬ся простейшим примером, так называемой динамической структуры данных. В динамических структурах данных объект содержится в различных участках памяти, количество и состав которых может меняться в процессе работы. Единство такого объекта поддерживается за счет объединения его частей в описании класса. Простейший линейный список представляет собой линейную последователь¬ность элементов. Для каждого из них, кроме последнего, имеется следующий элемент, и для каждого, кроме первого - предыдущий. Список традиционно изображают в виде последовательности элементов, каждый из которых со¬держит ссылку (указатель) на следующий и/или предыдущий элемент, однако заметим, что физически в представлении элементов списка может и не быть никаких ссылок.
Методы вычисления адреса. Пусть в каждом из М элементов массива Т содержится элемент списка (например целое положительное число). Если имеется некоторая функция H(V), вычисляющая однозначно по элементу V его адрес - целое положительное число из интервала [0,M-1],то V можно хранить в массиве T с номером H(V) т.е. V=T(H(V)). При таком хранении поиск любого элемента происходит за постоянное время не зависящее от M.
Массив T называется массивом хеширования, а функция H - функцией хеширования.
45)Работа со строками
Для обработки строк в программах, написанных на С, применяют билиотеку string.h. В нее входит достаточно большое количество функций. Перед использованием этой библиотеки следует ее подключить:
#include <string.h>
Создание строк Для создания (не в памяти, а их инициализации) строк применяют функции strcpy и strcat, а также несколько их аналогов. Перед использованием функции strcpy (STRing CoPY) следует проверить, выделена ли память под обе строки. Объявление функции копирования строк:
char *strcpy(char *dest, const char *src);
wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
char *strncpy(char *dest, const char *src, size_t maxlen);
wchar_t *wcsncpy(wchar_t *dest, const wchar_t *src, size_t maxlen);
Общее их значение таково: строка, находящаяся в src помещается в dest. Если Вы хотите ограничить количество копируемых символов (это бывает полезно, когда длина строки ограничена) следует использовать функцию strncpy. Функции возвращают указатель на полученную строку.
Для того, чтобы прибавить к строке другую, программисты используют функцию strcat (STRing conCATenate). Объявление функции добавления строк:
char *strcat(char *dest, const char *src);
wchar_t *wcscat(wchar_t *dest, const wchar_t *src);
Эти функции добавляют строку src в конец строки dest. За счет того, что функции возвращают указатель на полученную строку, имеется возможность использовать вложенные вызовы. Премер использования функций создания строк.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
