- •Оценка эффективности алгоритмов
- •Целочисленная арифметика
- •Дано натуральное число. Выяснить является ли оно палиндромом, то есть читается справа налево и слева направо одинаково
- •Дано натуральное число. Выяснить соотношение между количествами двоек и пятерок в этом числе
- •Найти самую большую и самую маленькую цифры данного натурального числа
- •Выяснить образуют ли цифры натурального числа возрастающую последовательность
- •Формат выходного файла
- •Формат входного файла
- •Формат выходного файла
- •Формат входного файла
- •Формат входного файла
- •Формат выходного файла
- •Длинная арифметика
- •Выходные данные
- •Задачи Задача 52 Иностранные земли
- •Входные данные.
- •Выходные данные.
- •Формат входного файла
- •Формат выходного файла
- •Задачи Задача 56 Уравнение
- •Решение
- •Одномерные массивы
- •Базовые задачи на массивы
- •Задача 15 Сокращение одночленов
- •Входные данные:
- •Задача 16 Школьный субботник
- •Входные данные:
- •Входные данные:
- •Выходные данные:
- •Примеры
- •Задача 27 Решение систем линейных уравнений на Pascal
- •Двумерные массивы
- •Описание массива
- •Способы создания массива
- •Задачи:
- •Задача 5 Малыш играет в "Морской бой 2" Малыш играет в "Морской бой". Поле для игры представляет собой квадрат
- •Входные данные
- •Выходные данные
- •Задача 26 Шарик в лабиринте
- •Примечание
- •Задача 27 Блохи
- •В первой строке входного файла Input.Txt находится 5 чисел, разделенных пробелом: n, m, s, t, q.
- •Входные данные
- •Выходные данные
- •Примеры
- •Задача 34 Магический квадрат
- •Формат входного файла
- •Формат выходного файла
- •Входные данные
- •Выходные данные
- •Входные данные
- •Выходные данные
- •Рекурсия
- •Комбинаторика
- •2.5. Генерация комбинаторных объектов
- •Множество всех подмножеств
- •Перестановки
- •Размещения
- •Перестановки с повторениями
- •Сочетания с повторениями
- •Перебор
- •Символ o()
- •Отсечение по времени
- •Рассмотрим несколько олимпиадных задач.
- •Шарик в лабиринте
- •Задача 1. Шарик в лабиринте
- •Задача 3 Цепочка слов
- •Входные данные
- •Выходные данные
- •Примеры
- •Формат входного файла
- •Формат выходного файла
- •Примеры
- •Динамическое программирование
- •Задача 8 Гвоздики
- •Задача 13 Лесенки
- •Задача 18 Свинья-копилка
- •Входные данные
- •Выходные данные
- •Задача 13 Лесенки Лесенкой называется набор кубиков, в котором каждый более верхний слой содержит кубиков меньше, чем предыдущий.
- •Задача 18 Свинья-копилка
- •Формат входного файла:
- •Формат выходного файла:
- •Примеры
- •Решение
- •Входные данные:
- •Выходные данные:
- •Формат входа
- •Формат выхода
- •Задача 39 Лесенка-2
- •Входные данные
- •Выходные данные
- •Примеры
- •Системы счисления
- •Задача 11 Троичная сбалансированная система счисления
- •Алгоритм перевода
- •Процедуры и функции для работы с символами и строками
- •Определить количество слов в строке
- •Получите строковой массив из всех слов данной строки
- •Получите строковой массив из всех слов данной строки и
- •Получите строковой массив из всех слов данной строки и
- •Составьте программу, определяющую, является ли введенное слово изображением числа
- •Введите 2 целых числа. Преобразуйте числа в две строки, объедините их в одну строку и выведите результат на экран.
- •Вычислите длину самого короткого и самого длинного слов в строке
- •Подсчитайте количество букв в каждом слове данной строки
- •Дана строка. Определить количество слов этой строки, в которых есть ровно две буквы «е»
- •Составьте программу, удаляющую все лишние пробелы из введенной строки
- •Напишите программу, сортирующую символы введенной с клавиатуры строки в порядке возрастания их номеров в ascii-таблице. Например, если введено: 'cba', в результате надо получить ‘abc’.
- •В тексте, состоящем из маленьких латинских букв , подсчитайте количество гласных букв
- •Заданы фамилия, имя и отчество учащегося, разделенные пробелом. Напечатайте его фамилию и инициалы.
- •Сложное слово состоит из двух частей одинаковой длины и соединительной гласной. Найдите обе части этого слова.
- •Вычеркните из слова х те буквы, которые встречаются в слове z
- •Подсчитайте число различных букв в слове
- •Даны два слова. Составьте программу, определяющую можно или нет из букв слова а составить слово в.
- •Даны два слова. Являются ли они анаграммами
- •Является ли данная строка палиндромом?
- •Задача 4. Сокращение одночленов
- •Входные и выходные данные
- •Это чисто техническая задача на аккуратное программирование.
- •Задача 6 Текст
- •Входной файл Input.Txt в первой строке входного файла находится 5 чисел,разделенных пробелом: n, m, s, t, q.
- •Бинарные деревья. Алгоритм HeapSort
- •Поиск в глубину в графе
- •Алгоритм Флойда поиска кратчайших расстояний и кратчайших путей
- •Бинарные деревья. Алгоритм HeapSort
- •Графызадачи Двоичная куча
- •Примеры задач, которые решаются с помощью двоичной кучи
- •Поиск максимального потока методом Форда-Фалкерсона на Pascal
- •Графызадачи Поиск сильно связанных компонент на Pascal
- •Поиск точек раздела, мостов и двусвязных компонент
- •Идеи алгоритмов
- •Точки раздела
- •Двусвязные компоненты
- •Задача 21 Моя Столица
- •Вычислительная геометрия
- •3. Уравнение прямой 2
- •4. Уравнение прямой проходящей через точку м(х0у0)
- •Формат входного файла
Перестановки
Пусть мы имеем 4 компонента, обозначенные буквами A, B, C, D. Тогда множество всех перестановок из этих компонент будет включать следующие элементы: ABCD, BACD, CABD, DABC, ABDC, BADC, CADB, DACB, ACBD, BCAD, CBAD, DBAC, ACDB, BCDA, CBDA, DBCA, ADBC, BDAC, CDAB, DCAB, ADCB, BDCA, CDBA, DCBA. Приведем алгоритм построения следующей перестановки 9 компонент, обозначенных цифрами от 1 до 9. Первая из таких перестановок - это:
1 2 3 4 5 6 7 8 9.
Пусть текущая перестановка из 9 компонент:
1 9 5 8 4 7 6 3 2.
Какой будет следующая перестановка, если мы строим перестановки в лексикографическом порядке (то есть в порядке возрастания величины числа, составленного из этих цифр)? Правильный ответ таков:
1 9 5 8 6 2 3 4 7.
Как он получается? Прежде всего необходимо просматривать исходный массив от конца к началу, чтобы найти первое число, которое меньше предыдущего; в нашем случае - это 4 (7 < 6 < 3 < 2, а 4 < 7). Далее среди просмотренных чисел справа от найденной четверки мы ищем последнее число, которое больше 4. Это число 6 (7 > 4, 6 > 4, 3 < 4, 2 < 4). Затем меняем эти 2 найденных числа (4 и 6) местами и получаем: 1 9 5 8 6 7 4 3 2.
И теперь числа (справа от 6), которые составляют убывающую последовательность (7 4 3 2), попарно меняем местами так, чтобы они составили возрастающую последовательность (2 3 4 7):
1 9 5 8 6 2 3 4 7.
Это и есть следующая перестановка. А какая перестановка будет последней для данного примера? Надеюсь, что вдумчивый читатель догадался и сам:
9 8 7 6 5 4 3 2 1.
Неформально алгоритм построения очередной перестановки по текущей может быть записан следующим образом:
От конца к началу перестановки ищем первый элемент B[i] такой, что B[i] < B[i + 1].
Запоминаем его индекс - I.
От элемента I + 1 до конца ищем последний элемент, больший, чем B[i], и запоминаем его индекс - K.
Меняем местами эти элементы с номерами I и K.
Всю группу элементов от (i + 1)-го элемента до N-го попарно меняем местами: (i + 1)-й элемент с N-м, (i + 2)-й элемент с (N - 1)-м и т. д.
Формализованный алгоритм генерации всех перестановок из N элементов может выглядеть следующим образом: Ввод N Прописываем массив B последовательно числами от 1 до N Это первая - начальная - перестановка, выводим ее Пока (истина) i=N Пока (i>0) и (B[i]>=B[i+1]), i=i-1 Если i=0, то конец работы Для j от i+1 до N если B[j]>B[i], то K=j Обмен значений B[i] и B[k] Для j от i+1 до (i+ ((N+1-i) div 2)) Обмен значений B[j] и B[N+i+1-j] Вывод текущей перестановки B Понятно, что цикл парных перестановок «хвоста» массива B нельзя делать от (i + 1)-го до N-го элемента, иначе элементы поменяются местами по два раза и получится, что ничего не изменилось. Цикл нужно выполнить для половины этого «хвоста». Этому и служит несколько сложное для понимания значение конечной переменной цикла: i + (N + 1 - i) div 2. Понятно, что цикл парных перестановок «хвоста» массива B нельзя делать от (i + 1)-го до N-го элемента, иначе элементы поменяются местами по два раза и получится, что ничего не изменилось. Цикл нужно выполнить для половины этого «хвоста». Этому и служит несколько сложное для понимания значение конечной переменной цикла: i + (N + 1 - i) div 2.
Листинг 2.39. Программа, генерирующая перестановки из N компонент const alphabet : string[26] = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; var b : array [1..100] of byte; N,i,j,k : byte; Procedure SwapB(i,k:byte); var x : byte; begin x:=B[i]; B[i]:=B[k]; B[k]:=x; end; Procedure WriteB; begin for i:=1 to N do write({alphabet[b[i]]); writeln; end; begin readln(N); for i:=1 to N do b[i]:=i; WriteB; while (true) do begin i:=N; while (i>0) and (B[i]>=B[i+1]) do i:=i-1; if i=0 then exit; for j:=i+1 to N do if (B[j]>B[i]) then K:=j; SwapB(i,k); for j:=i+1 to (i+ ((N+1-i) div 2)) do SwapB(j,N+i+1-j); writeB; end; end. В программе, генерирующей все перестановки из N компонент, обозначенных за-главными буквами латинского алфавита (листинг 2.39), введены две процедуры: WriteB и SwapB
Процедура WriteB вызывается всякий раз, когда построена очередная перестановка. В данной программе процедура WriteB просто выводит соответствующую по-следовательность
латинских букв. Процедура SwapB(i,k) введена для упрощения понимания главной программы. SwapB просто обменивает значениями два элемента массива B, которые имеют индексы, соответствующие значениям параметров процедуры i и k. Процедура SwapB используется в тексте программы два раза: 1) при обмене значениями двух найденных элементов с индексами I и K; 2) при обеспечении попарного обмена элементов «хвоста», в котором текущий элемент с индексом j обменивается местами со своим «партнером», находящимся на позиции N + i + 1 - j. Таким образом, (I + 1)-й элемент поменяется (при J=I+1) местами с N-м элементом, (I + 2)-й элемент (при J=I + 2) - с (N - 1)-м и т. д. Общее число перестановок из N элементов равно N! (читается - N факториал). Напомним, что N! = 1 * 2 * 3 * ... * N. Сочетания Пусть имеем 5 компонент, обозначенных латинскими буквами A, B, C, D, E. Тогда все сочетания из этих 5 компонент по 3, выписанные в лексикографическом порядке, будут таковы:
для букв - ABC, ABD, ABE, ACD, ACE, ADE, BCD, BCE, BDE, CDE;
для цифр - 123, 124, 125, 134, 135, 145, 234, 235, 245, 345.
Неформально алгоритм генерации последовательности чисел в лексикографиче-ском порядке можно записать следующим образом: выберем наименьшие M из имеющихся N чисел и выпишем их в порядке возрастания (в нашем примере - 1 2 3), - это будет начальным сочетанием. Очевидно, что наибольшие M чисел из имеющихся (3 4 5), выписанные в порядке возрастания, составят последнее сочетание. Для того чтобы по текущему сочетанию получать следующее, можно поступать таким образом: находим позицию в текущем сочетании, на которой не стоит по-следнее из возможных значений, и затем увеличиваем его на 1. А все последу-ющие элементы сочетания получаем увеличением на 1 предыдущего элемента сочетания. Например, пусть текущее сочетание таково:
1 3 5.
Анализ начинаем с последней позиции сочетания. 5 - это последнее возможное значение, потому переходим к предыдущей позиции. 3 - это не последнее возможное значение для этой позиции (каковым является 4 в данном случае). Поэтому мы его увеличиваем на 1 и получаем 4. Число в следующей позиции получаем прибавлением 1 к этой 4 и получаем 5. Таким образом следующее сочетание будет:
1 4 5.
Более строго этот алгоритм может быть записан следующим образом: Ввод N, M (из сколька, по сколько)
Заносим в массив B числа от 1 до M Это первое сочетание, выводим его Пока (истина) i=M Пока (i>0) и (b[i]=N-m+i), i=i-1 Если i=0, то работа завершена B[i]=B[i]+1 Для j от i+1 до M B[j]=B[j-1]+1; Вывод B - следующей перестановки Листинг 2.40. Программа, выводящая в лексикографическом порядке все сочетания из N латинских букв по M uses crt; const alphabet : string[26] = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; var b : array [1..100] of byte; N,M,i,j,k : byte; Procedure WriteB; begin for i:=1 to M do write(alphabet[b[i]]); writeln; end; begin readln(N,M); for i:=1 to M do b[i]:=i; WriteB; while (true) do begin i:=M; while (i>0) and (b[i]=N-m+i) do Dec(i); if i=0 then exit; Inc(B[i]); for j:=i+1 to M do B[j]:=B[j-1]+1; WriteB; end; end. Напомним, что общее число сочетаний из N элементов по M может быть вычислено по формуле:
