Введение В данном пособии приводятся дополнительные материалы по алгоритмам дискретной математики, которые не изучались в начальной части курса “Алгоритмы и структуры данных” и редко упоминаются в других учебных курсах. Большинство задач носит олимпиадный характер, но значение рассматриваемых подходов шире. Практика показывает, что студенты значительно лучше преуспевают в технике программирования, а не в разработке рациональных алгоритмов. Общими недостатками является неумение оценить объем вычислений, сравнить различные подходы к решению задачи, выбрать подходящие структуры данных, провести полное и грамотное тестирование программы. Основными показателями эффективности являются трудоемкость алгоритмов и затраты оперативной памяти при их программной реализации. В первую очередь оценивают зависимость этих показателей от размерности исходных данных N. В математике пропорциональность какого-либо показателя величине F(N) принято обозначать O(F(N)). Часто рациональные структуры данных позволяют без особых затруднений обойтись затратами памяти O(N). В этом случае основное внимание уделяют оценке трудоемкости. Переборные алгоритмы имеют обычно экспоненциальную трудоемкость, то есть объем вычислений оценивается как O(Exp(N)). Такие алгоритмы реализуемы только при ограниченных значениях N. Полиномиальные алгоритмы имеют оценку O(NP), где P>0. Величина коэффициента пропорциональности отступает на второй план в тех случаях, когда размерность данных велика. Сравним, например, два алгоритма с трудоемкостью 0,1N2 и 100N. При N < 1000 первый алгоритм эффективнее. Но при N = 105 второй алгоритм в 100 раз быстрее первого. К сожалению, студенты часто не принимают во внимание трудоемкость алгоритмов. Многие простодушно считают, что отладка приложения на небольших по объему тестах при современной скорости компьютеров достаточна для окончательного успеха. Это не так. Рассмотрим наглядный пример. Пусть требуется найти кратчайший путь между двумя заданными вершинами на графе из 30 вершин, каждая из которых связана со всеми другими. Такой граф трудно считать большим. Как известно из начальной части курса [15], для решения этой задачи часто используют алгоритм Дейкстры, трудоемкость которого имеет оценку O(N2). Попробуем найти кратчайший путь перебором всевозможных путей, что проще всего реализуется поиском с возвратами. Ограничимся для простоты только путями, включающими все вершины графа. Поскольку в промежутке между начальной и конечной вершинами могут в различном порядке находиться 28 вершин, то таких путей 28! Эта величина превышает 1029. Будем считать, что мы в состоянии находить и оценивать 109 путей в секунду (реально значительно меньше). Значит, нам потребуется 1020 секунд для просмотра всех путей. В сутках менее 105 секунд, а в году менее 500 суток, то есть поиск займет более 21012 лет. И это при том, что мы рассматривали только самые длинные по числу вершин пути! Нас не спасет даже компьютер, работающий в 1000 раз быстрее. Однако студенты редко проводят подобные оценки. Одна и та же задача может решаться разными по трудоемкости алгоритмами. Нахождение более быстрых алгоритмов часто ведет к прорыву в различных проблемах, как теоретических, так и практических. Например, быстрые алгоритмы работы со строками лежат в основе поисковых систем Интернета. Не стоит, тем не менее, забывать и про организацию данных. Во многих случаях высокая скорость работы достигается путем использования рациональных структур данных. Так, быстрый поиск информации в современных системах управления базами данных основан на Б-деревьях и хеш-таблицах. Другими примерами удачных структур данных являются дерево отрезков и дерево Фенвика, рассматриваемые в пособии. Впрочем, каждая структура данных тесно связана с использующими ее алгоритмами. 2 Во всех задачах исходные данные задаются в файле INPUT.TXT, а результат выводится в файл OUTPUT.TXT. Если в некоторой строке этих файлов несколько элементов, представленных более чем одним символом, то они разделяются пробелами. На одном тесте время работы не должно превышать 2 секунд, а затраты оперативной памяти 256 мегабайтов. Изменение этих условий оговаривается специально. Размерность исходных данных во многих постановках задач рассчитана на применение 32-разрядной среды, такой как Delphi или Virtual Pascal. Рекомендуется сразу ориентироваться на максимальную размерность данных. Например, стоит применять быструю сортировку массивов, не злоупотреблять последовательным поиском данных и т. п. В С++ программная реализация может значительно упроститься путем использования библиотеки шаблонов STL. Обязательным этапом проверки эффективности программ должно быть нагрузочное тестирование, то есть выполнение тестов максимальной размерности. 1. Перебор с возвратом При переборе с возвратом последовательно достраивается единственное частичное решение. В этом и состоит сущность поиска в глубину: продолжать расширение исследуемого решения до тех пор, пока это возможно, и когда решение нельзя расширить, возвращаться по нему и пытаться сделать другой выбор на самом близком шаге, где имеется такая возможность. Если нужно найти все решения, то после нахождения очередного из них также производится возврат. Идею перебора с возвратом легче всего понять на примере следующей задачи прохода через лабиринт. На клетчатой бумаге имеется прямоугольник. Заданы отрезки прямых, отделяющие клетки друг от друга и определяющие лабиринт. Требуется из начальной клетки попасть в конечную за некоторое число ходов. Ход состоит в перемещении из текущей клетки в соседнюю слева, справа, сверху либо снизу в пределах прямоугольника без пересечения отрезков прямых. Например, в этом лабиринте требуется попасть их левого нижнего угла в правый верхний. Один из способов прохода через лабиринт – двигаться из начальной клетки в соответствии с двумя правилами: 1. В каждой клетке выбирать еще не исследованный путь. 2. Если из текущей клетки нет неисследованных путей, то нужно вернуться назад на ту клетку, из которой пришли в текущую. Первое правило говорит о том, как расширить исследуемый путь, если это возможно, а второе правило – о том, как выходить из тупика. В этом и состоит сущность поиска с возвратом: продолжать расширение исследуемого решения до тех пор, пока это возможно, и когда решение нельзя расширить, возвращаться по нему и пытаться сделать другой выбор на самом близком шаге, где имеется такая возможность. Если нужно найти все решения, то после нахождения очередного из них также производится возврат. 3 В общем случае решение задачи состоит из вектора (a1, a2, … ) конечной, но не определенной длины, удовлетворяющего некоторым ограничениям. Каждое ai является элементом конечного линейно упорядоченного множества Ai. При полном переборе должны рассматриваться элементы множества A1 A2 … Ai для i = 1, 2,…Здесь символ ‘’ обозначает декартовое произведение множеств. В качестве исходного частичного решения выбирается пустой вектор ( ) и на основе имеющихся ограничений выясняется, какие элементы из A1 являются кандидатами в a1; обозначим это подмножество через S1. В качестве a1 выбирается первый элемент множества S1. В результате получается частичное решение (a1). Далее в соответствии с ограничениями и выбранным элементом a1 выбирается элемент a2 из множества S2 и т. д. Если на шаге k частичное решение (a1, a2, …, ak-1) не представляет возможностей для выбора элемента ak, то выбирается новый элемент ak-1. Если ak-1 выбрать нельзя, возвращаемся еще дальше и выбирается новый элемент ak-2 и т. д. Этот процесс удобно описать с помощью дерева. Начало Выборы для a1 Выборы для a2 при данном a1 Выборы для a3 при данных a1 и a2 …………………. Обход дерева в порядке сверху вниз соответствует схеме поиска с возвратом. При обходе нужно стремиться максимально полно использовать имеющиеся ограничения, избегая лишних вычислений. Например, при проходе по лабиринту может выясниться, что все пути из некоторой клетки ведут в тупики. Если не требуется перечислять все решения, то нет смысла повторно заходить на эту клетку. Распространенным примером применения перебора с возвратом является задача о восьми ферзях [1]. Требуется расставить на шахматной доске 8 ферзей так, чтобы они не атаковали один другого. Иными словами, они должны стоять на разных горизонталях, вертикалях и диагоналях. В каждой строке должен находиться ровно один ферзь, поэтому решение можно представить вектором (a1, a2, …, a8), в котором ai – номер столбца ферзя из строки с номером i. Более того, в каждом столбце должен быть ровно один ферзь, поэтому ai ≠ aj при i ≠ j. Наконец, поскольку ферзи не должны атаковать друг друга по диагонали, то необходимо выполнение условия |ai - aj| ≠ |i-j| , если i ≠ j. Указанные ограничения существенно снижают размерность задачи. Существуют 8 8 вариантов расположения ферзей по одному в каждой строке, 8!=40320 вариантов с учетом того, что ферзи должны быть в разных столбцах, и всего 2096 вариантов, учитывая дополнительно их расположение на разных диагоналях. Поставим первого ферзя в одной из клеток на первой горизонтали. На второй горизонтали расположим второго ферзя с учетом ограничений и т. д. При невозможности установки очередного ферзя или после нахождения решения возвратимся к расположению предыдущего ферзя. Можно добавить еще ряд ограничений, считая эквивалентными два решения, если одно из них переводится в другое с помощью комбинации вращений и отражений. Для программирования задач перебора с возвратом удобно использовать стек, реализуемый явно или с помощью рекурсии. Новый элемент частичного решения 4 включается в стек, а при возврате к предыдущему частичному решению происходит удаление из стека. Приведем программу расстановки ферзей для переменного размера доски. Program Ferzi; { Расстановка N ферзей на доске NN, не бьющих друг друга. Выдача в файл out.txt. Количество вариантов по размеру доски: для 1 – 1, для 2 – 0, для 3 – 0, для 4 – 2, для 5 - 10 для 6 – 4, для 7 – 40, для 8 – 92, для 9 – 352, для 10 - 724 для 11 – 2680, для 12 - 14200 } Uses Crt; Var Ch: array[1..20] of char; {символьное обозначение вертикалей доски} Sc: array[1..20] of integer;{счетчики для строк (положения ферзей)} N,i,j,k,m: integer; F: text; {для найденных позиций} Poz: array [1..20] of integer; {индекс-номер строки, значение-номер позиции (столбца), где ферзь} Flag: boolean; Procedure OutPoz; {выдача позиции} Begin For i:=1 to N do Write(F,Ch[i],Poz[i],' '); j:=j+1; {количество позиций} WriteLn(F) End; Begin {начало основной программы} ClrScr; Write('Введите размер доски (до 12) '); ReadLn(N); if (N<1) or (N>12) then begin WriteLn(' Недопустимый размер, до новых встреч!'); ReadLn; Halt end; j:=ord('a'); For i:=1 to N do {присвоение обозначений столбцам доски} begin Ch[i]:=Chr(j); j:=j+1 end; j:=0; {счетчик общего количества позиций} Assign(F,'out.txt'); Rewrite(F); WriteLn(F,' Позиции для ',N,' ферзей:'); For i:=1 to N do Sc[i]:=0; {счетчики позиций(столбцов) по строкам} k:=1; {номер строки} While k>0 do {для перебора - стек по строкам} begin Sc[k]:=Sc[k]+1; {номер столбца} While Sc[k]<=N do begin m:=Sc[k]; {далее: можно ли ставить очередного ферзя на клетку (k,m)?} Flag:=false; 5 For i:=1 to k-1 do if (m=Poz[i]) or (Abs(k-i)=Abs(m-Poz[i])) then {клетка (k,m) в одном столбце или на одной диагонали с i-м ферзем} begin Flag:=true; Break end; if Flag then {клетка (k,m) под боем предыдущих ферзей} begin Sc[k]:=Sc[k]+1; {следующая позиция в строке} if Sc[k]<=N then Continue {на анализ следующей позиции} else Break {ферзь в строке k разместить не удалось, отступаем на предыдущую строку} end else {клетка (k,m) пригодна для следующего ферзя} begin Poz[k]:=m; if k=N then OutPoz {размещен последний ферзь, вывод расположения ферзей} else k:=k+2; { после следующего оператора Break будет k:=k-1} Break end; end; {конец цикла While по столбцам строки k} Sc[k]:=0; {может выполняться при k=N+1} k:=k-1; end; {конец цикла While по строкам} WriteLn(F,' Общее количество позиций ', j); Close(F); WriteLn End. В основной части курса [9] уже встречался поиск путей между двумя вершинами на графе в глубину. При наличии каких-либо ограничений можно, как и в предыдущей задаче, отсекать бесперспективные для дальнейшего исследования вершины. Рассмотрим еще одну распространенную задачу, для решения которой используется поиск в глубину [2]. Грядки. Прямоугольный садовый участок шириной N и длиной M метров разбит на квадраты со стороной 1 метр. На этом участке вскопаны грядки. Грядкой называется совокупность квадратов, удовлетворяющая таким условиям: из любого квадрата этой грядки можно попасть в любой другой квадрат этой же грядки, последовательно переходя по грядке из квадрата в квадрат через их общую сторону; никакие две грядки не пересекаются и не касаются друг друга ни по вертикальной, ни по горизонтальной сторонам квадратов (касание грядок углами квадратов допускается). Подсчитайте количество грядок на садовом участке. Ввод из файла INPUT.TXT. В первой строке находятся числа N и M через пробел, далее идут N строк по M символов. Символ # обозначает территорию грядки, точка соответствует незанятой территории. Других символов в исходном файле нет. Вывод в файл OUTPUT.TXT. Вывести одно число - количество грядок на участке. Ограничения: 1 ≤ N, M ≤ 200. 6 Пример Ввод 5 10 ##......#. .#..#...#. .###....#. ..##....#. ........#. Вывод 3 В терминах компьютерной графики мы имеем дело с 4-связными областями, каждую из которых можно обойти ходом шахматной ладьи. Следует в любом порядке пройти по всем клеткам поля. Если клетка содержит символ ‘#’ (начало новой грядки), нужно заполнить всю 4-связную область символами ‘.’. Удобно организовать барьер, объявив массив клеток с запасом на 1 в каждую сторону и заполнив его перед чтением файла символами ‘.’. Ответом задачи будет количество вызовов извне процедуры перекраски, которая в простейшем случае выглядит так: Procedure Metka (i,j: integer); {окраска (пометка грядки) символами '.'} Begin if C[i,j] = ’#’ then begin C[i,j] := ‘.’; {пометка клетки (i,j) как пройденной} Metka (i+1,j); Metka (i-1,j); Metka (i,j+1); Metka (i,j-1); end; Можно применять явный стек вместо рекурсивного. Приведем этот вариант программы. Использование динамической памяти позволяет даже в среде Турбо Паскаля увеличить в несколько раз размер поля. Program Beds; {заливка с явным стеком} Const Max=200; Type Stack = array[1..Max*Max] of byte; {чтобы хватило памяти} Var X,Y: ^Stack; {для координат клеток} i,j: integer; Top: word; {счетчик для стека} Fin,Fout: text; N,M: integer; {размер участка} C: array[0..Max+1,0..Max+1] of char; {карта поля (с барьерами по краям)} Count: integer; {счетчик количества грядок} Procedure Pop(Var i,j: integer); {извлечение из стека очередной клетки грядки} Begin i:=X^[Top]; j:=Y^[Top]; 7 Top:=Top-1; End; Procedure Push(i,j: integer); {занесение в стек очередной клетки грядки и ее перекраска} Begin if C[i,j]='#' then {чтобы не проверять 4 раза в вызывающей процедуре Metka} begin Top:=Top+1; X^[Top]:=i; Y^[Top]:=j; C[i,j]:='.'; {пометка клетки (i,j) как пройденной} end; End; Procedure Metka(i,j: integer); {окраска (пометка) грядки символами '.'} Begin Top:=0; {начало окраски клеток новой грядки} Push(i,j); {занесение клетки (i,j) в стек и перекраска} While Top>0 do {пока стек непуст} begin Pop(i,j); {извлечение из стека очередной клетки грядки(Pop)} Push(i+1,j); Push(i-1,j); Push(i,j+1); Push(i,j-1); end End; Begin For i:=0 to N+1 do {для барьера} For j:=0 to M+1 do C[i,j]:='.'; Assign(Fin,'input.txt'); Reset(Fin); ReadLn(Fin,N,M); For i:=1 to N do begin For j:=1 to M do Read(Fin,C[i,j]); ReadLn(Fin); {перевод строки} end; Close(Fin); New(X); New(Y); Count:=0; For i:=1 to N do For j:=1 to M do if C[i,j]='#' then {встретили новую грядку} begin Count:=Count+1; Metka(i,j) end; Dispose(X); Dispose(Y); Assign(Fout,'output.txt'); Rewrite(Fout); WriteLn(Fout,Count); Close(Fout); End. 8 Задачи для самостоятельного решения 1.1. Покраска лабиринта (5) Лабиринт представляет собой квадрат, состоящий из NxN сегментов. Каждый из сегментов может быть либо пустым, либо заполненным монолитной каменной стеной. Гарантируется, что левый верхний и правый нижний сегменты пусты. Лабиринт обнесён сверху, снизу, слева и справа стенами, оставляющими свободными только левый верхний и правый нижний углы. Директор лабиринта решил покрасить стены лабиринта, видимые изнутри (см. рисунок). Помогите ему рассчитать количество краски, необходимой для этого. Ввод из файла INPUT.TXT. В первой строке находится число N, затем идут N строк по N символов: точка обозначает пустой сегмент, решётка - сегмент со стеной. Вывод в файл OUTPUT.TXT. Вывести одно число - площадь видимой части внутренних стен лабиринта в квадратных метрах. Ограничения: 3 N 33, размер сегмента 3 x 3 м, высота стен 3 м, время 1 с. Пример Ввод 5 ..... ...## ..#.. ..### ..... Вывод 198 1.2. Скобки (4) При заданном четном N (N 16) перечислить все правильные скобочные формы длины N из скобок ‘(‘, ‘)’, ’[‘, ’]’. Ввод из файла INPUT.TXT. В единственной строке задается число N. Вывод в файл OUTPUT.TXT всех виде правильных скобочных форм. Пример Ввод 5 Вывод (()) ([]) ()() ()[] [()] [[]] []() [][] Подсказка. Поиском в глубину организовать ограниченный перебор по позициям строки. Нужно учитывать число вложенных открывающих скобок, поскольку потребуется такое же количество закрывающих. Возможность добавления закрывающей скобки без нарушения синтаксиса проверяется с помощью стека. 1.3. Шпионские хлопоты (8) Прямоугольная секретная зона разделена на квадратные клетки одинакового размера. Некоторые клетки целиком заняты психотронами – генераторами психической энергии. 9 Психотроны способны действовать только все вместе, поэтому занятые клетки представляют собой 8-связную область. Это означает, что любые две занятые клетки либо непосредственно соприкасаются друг с другом стороной или углом, либо связаны таким же образом через промежуточные клетки. Приехавший шпион совершает обход зоны по замкнутому маршруту. Его задача – разглядеть в бинокль наибольшую протяженность границ занятых психотронами клеток с расстояния, не превышающего половины стороны клетки. В то же время он не может подойти к любому психотрону ближе, не рискуя здоровьем. Найти минимальную длину безопасного маршрута шпиона. Ввод из файла INPUT.TXT. Первая строка содержит целые числа M, N и L через пробел, где M и N – длина и ширина зоны в клетках, а L – длина стороны клетки. В следующих M строках заданы через пробел N чисел – нулей или единиц. Единицы отмечают занятые психотронами клетки зоны. Вывод в файл OUTPUT.TXT. Единственная строка содержит результат в виде дробного числа с точностью до одного десятичного знака. Ограничения: 1 ≤ L ≤ 100; 1 ≤ M ≤ 50; 1 ≤ N ≤ 50. Пример Ввод 2 3 20 0 1 1 0 1 1 Вывод 222.8 1.4. Реликтовая роща (6) В заповеднике растет роща реликтовых деревьев. Для их защиты требуется обнести рощу забором. Но для обеспечения доступа к остальной территории заповедника площадь участка, окруженного забором, должна быть минимальной. Деревья растут точно в узлах координатной сетки на расстоянии одного метра друг от друга. Любое из деревьев имеет хотя бы одного соседа (с юга, севера, востока или запада). Забор состоит из блоков длиной в один метр. Чтобы огородить одно дерево необходимо 4 блока забора: А чтобы огородить такую группу из 9 деревьев нужно 20 блоков: По заданной конфигурации рощи найти минимально необходимое число блоков для забора. Ввод. В первой строке записаны через пробел два числа N и K (1 N, K 300)– количество строк и столбцов данных. В следующих N строках содержатся последовательности из K символов (единиц или нулей). Единицей обозначается расположение реликтового дерева, а нулем – его отсутствие в узле координатной сетки. Вывод. В единственной строке выводится число блоков забора, необходимое для огораживания. Примеры Ввод 1 Ввод 2 3 6 5 7 001110 0101010 011011 1111111 011110 0101010 1100011 0111110 Вывод 1 Вывод 2 16 32 10 1.5. Информатизация садоводства (8) Дачный участок Степана Петровича имеет форму прямоугольника размером a b. На участке имеется n построек, причем основание каждой постройки — прямоугольник со сторонами, параллельными сторонам участка. Вдохновленный успехами соседей, Степан Петрович хочет посадить на своем участке m видов плодовых культур (участок Степана Петровича находится в северной местности, поэтому m = 1 или m = 2). Для каждого вида растений Степан Петрович хочет выделить отдельную прямоугольную грядку со сторонами, параллельными сторонам участка. Само собой, грядки не могут занимать территорию, занятую постройками или другими грядками. Степан Петрович хочет расположить грядки таким образом, чтобы их суммарная площадь была максимальной. Грядки не должны пересекаться, но могут касаться друг друга. грядка №1 сарай Дом грядка №2 Требуется написать программу, которая по заданным размерам участка и координатам построек определяет оптимальное расположение планируемых грядок. Ввод. В первой строке входного файла содержатся два целых числа n и m (0 ≤ n ≤ 10; 1 ≤ m ≤ 2). Во второй строке содержатся два целых числа a и b (1 ≤ a, b ≤ 10000). Далее следуют n строк, каждая из которых содержит четыре целых числа xi,1, yi,1, xi,2, yi,2 –координаты двух противоположных углов постройки (0 xi,1 < xi,2 a, 0 yi,1 < yi,2 b). Различные постройки не могут пересекаться, но могут касаться друг друга. Вывод. Необходимо вывести m строк, каждая из которых содержит координаты двух противоположных углов предполагаемой грядки. Координаты должны быть целыми (всегда можно добиться максимальной суммарной площади грядок, располагая их в прямоугольниках с целыми координатами). В случае, если в вашем решении Степану Петровичу следует расположить менее m грядок, необходимо вывести для грядок, которые не следует сажать, строку «0 0 0 0» (см. второй пример). Примеры Ввод 1 Ввод 2 2 2 3 2 7 5 4 4 4 2 6 4 0 0 4 1 0 1 2 2 0 1 1 4 3 1 4 4 Вывод 1 Вывод 2 0 2 4 5 1 1 3 4 2 0 7 2 0 0 0 0 1.6. Домино (6) Имеется N костей игры домино. На каждой кости имеется 2 числа (каждое от 0 до 6). Требуется написать программу, которая будет определять максимальное число, составленное из цифр на костях цепочки, составленной по правилам домино из имеющихся костей. Ввод. Первая строка входного файла содержит целое число N – количество костей (2 N 30). Следующие N строк содержат два целых числа X и Y (0 X, Y 6), разделенные пробелом. Вывод. В выходной файл необходимо вывести максимальное целое число, цифры которого соответствуют значению костей в цепочке. Примеры Ввод 1 Ввод 2 Ввод 3 3 2 5 1 6 6 6 1 5 0 0 3 6 3 4 2 5 4 1 11 Вывод 1 61 Вывод 2 6663 1 6 1 0 Вывод 3 611443 2. Поиск в ширину. Волновой алгоритм Поиск в ширину также встречался в задаче поиска путей на графе [9]. Есть множество других задач, для решения которых используется этот же подход. Если при поиске в глубину последовательно достраивается единственное частичное решение, то при поиске в ширину происходит переход от одного частичного решения к другому. Поиск решения производится широким фронтом. Типичным примером поиска в ширину является алгоритм Дейкстры поиска кратчайшего пути на графе. Рассмотрим схему поиска в ширину на следующем примере. Игра Lines. В таблице из N строк и N столбцов некоторые клетки заняты шариками, другие свободны. Выбран шарик, который нужно переместить, и место, куда его нужно переместить. Выбранный шарик за один шаг перемещается в соседнюю по горизонтали или вертикали свободную клетку. Требуется выяснить, возможно ли переместить шарик из начальной клетки в заданную, и, если возможно, то найти путь из наименьшего количества шагов. Ввод из файла INPUT.TXT. В первой строке находится число N, в следующих N строках - по N символов. Символом точки обозначена свободная клетка, латинской заглавной O - шарик, @ - исходное положение шарика, который должен двигаться, латинской заглавной X - конечное положение шарика. Вывод в файл OUTUT.TXT. В первой строке выводится Y, если движение возможно, или N, если нет. Если движение возможно, далее следует N строк по N символов - как и на вводе, но буква X, а также все точки по пути заменяются плюсами. Ограничения: 2 ≤ N ≤ 40, время 1 с. Примеры Ввод 1 Ввод 2 Ввод 3 5 5 5 ....X ..X.. ...X. .OOOO ..... ..... ..... OOOOO O.OOO OOOO. ..... ..... @.... ..@.. ....@ Вывод 1 Вывод 2 Вывод 3 Y N Y +++++ ..++. +OOOO .++.. +++++ O+OOO OOOO+ .++++ @++++ ....@ Для решения задачи используется так называемый волновой алгоритм. В целях удобства организуем барьер, объявив двумерный массив от 0 до N+1 по каждому измерению. Во все барьерные клетки занесем признаки занятости в виде символов ‘O’. Это избавит нас от необходимости проверять каждый раз, находимся ли мы на краю поля. В начальную клетку поместим числовую метку 0. Далее во все соседние с ней пустые клетки занесем метку 1. Во все соседние клетки с меткой 1, помеченные символом ‘.’ как 12 свободные, поместим метку 2 и т. д. Будем считать на каждом шаге количество вновь занесенных меток. В конце концов, возможна одна из двух ситуаций: на очередном шаге помечена конечная клетка; новых меток не появилось. В первом случае значение метки K равно длине кратчайшего пути из начальной клетки в конечную. Сам путь восстанавливается в обратном направлении. Для конечной клетки находится одна из соседних к ней, имеющая метку K-1. Потом от нее находится следующая клетка с меткой K-2 и так до тех пор, пока не придем в начальную клетку. Второй случай говорит об отсутствии решения. Проще всего на каждом шаге находить все клетки с определенным значением метки полным перебором. Такой подход не годится для больших размерностей. В программе Lines, приведенной ниже, клетки, получающие очередные метки, записываются в кольцевую очередь. Выбор клеток из начала очереди обеспечивает просмотр по возрастанию меток. Program Lines; Const Max=150; Raz=10*Max; {максимальный размер очереди} Type Coord=record X,Y:byte; {координаты} end; Me=record X,Y: byte; {координаты} Metka: integer; {числовая метка} end; Var i,j,k,Met,p,q: integer; N,M: integer; {размер участка} C: array[1..Max,1..Max] of char; From: array[0..Max+1,0..Max+1] of char; {откуда получена метка: U-сверху, D-снизу, L-слева, R-справа} {используется также как рабочая карта поля с барьером из 'O'} Fin,Fout: text; Och: array[1..Raz] of Me; {кольцевая очередь для поиска в ширину} BegO,EndO,Count: integer; {для кольцевой очереди} Nach,Kon: Coord; {начальная и целевая клетки для поиска в ширину} b: boolean; {признак нахождения решения} Procedure Zanes(u,v: byte; Var Res: boolean); { занесение в конец кольцевой очереди } { (u,v)-текущая клетка, Res=true-дошли до конца } Begin if (u=Kon.X) and (v=Kon.Y) then Res:=true {достижение цели} else begin Res:=false; EndO:=(EndO mod Raz)+1; {кольцевая очередь} Och[EndO].X:=u; Och[EndO].Y:=v; Och[EndO].Metka:=Met+1; {текущая числовая метка} Count:=Count+1; end; 13 End; Begin Assign(Fin,'input.txt'); Reset(Fin); ReadLn(Fin,N); For i:=0 to N+1 do For j:=0 to N+1 do From[i,j]:='O'; {барьер} For i:=1 to N do begin For j:=1 to N do begin Read(Fin,C[i,j]); From[i,j]:=C[i,j]; { сначала копия C } if From[i,j]='@' then {начало} begin Nach.X:=i; Nach.Y:=j; From[i,j]:='O'; {запрет, чтобы не возвращаться} end; if From[i,j]='X' then {конец} begin Kon.X:=i; Kon.Y:=j; From[i,j]:='.'; end; end; ReadLn(Fin); {перевод строки} end; Close(Fin); BegO:=1; {кольцевая очередь для расстановки меток в ширину} EndO:=1; Count:=1; {длина очереди} Och[BegO].Metka:=0; Och[1].X:=Nach.X; Och[1].Y:=Nach.Y; {начальная точка} b:=false; While Count>0 do begin p:=Och[BegO].X; q:=Och[BegO].Y; Met:=Och[BegO].Metka; Och[BegO].X:=0; {для наглядности отладки} Och[BegO].Y:=0; BegO:=(BegO mod Raz)+1; Count:=Count-1; {выбор клетки из начала очереди} {далее занесение соседних клеток в конец очереди} if From[p,q+1]='.' then {можно идти направо} begin Zanes(p,q+1,b); {занесение в очередь} From[p,q+1]:='L'; {пришли слева} if b then Break; {достигли заданной клетки} end; if From[p+1,q]='.' then {можно идти вниз} begin Zanes(p+1,q,b); {занесение в очередь} From[p+1,q]:='U'; {пришли сверху} if b then Break; {достигли заданной клетки} end; 14 if From[p,q-1]='.' then {можно идти налево} begin Zanes(p,q-1,b); From[p,q-1]:='R'; {пришли справа} if b then Break; {достигли заданной клетки} end; if From[p-1,q]='.' then {можно идти вверх} begin Zanes(p-1,q,b); From[p-1,q]:='D'; {пришли снизу} if b then Break; {достигли заданной клетки} end; end; {здесь оказываемся либо при нахождении решения, либо по исчерпанию очереди, когда больше помечать нечего} Assign(Fout,'output.txt'); Rewrite(Fout); if b then {найдено решение} begin WriteLn(Fout,'Y'); p:=Kon.X; q:=Kon.Y; {восстановление от конца} For i:=1 to Met+1 do {клетку '@' не меняем} begin C[p,q]:='+'; Case From[p,q] of 'U': p:=p-1; 'D': p:=p+1; 'L': q:=q-1; 'R': q:=q+1; end; end; For i:=1 to N do begin For j:=1 to N do Write(Fout,C[i,j]); WriteLn(Fout); {перевод строки} end; end else WriteLn(Fout,'N'); Close(Fout); End. Задачи для самостоятельного решения 2.1. Квадратное озеро (6) Квадратное озеро с островами задается матрицей размером N N (1 N 300). Каждый элемент матрицы содержит либо символ '@' (собака), обозначающий территорию, которая включает часть острова, либо символ '.' (точка), обозначающий участок свободной воды. В левом верхнем углу озера находится квадратный плот размером M M (1 M < N) клеток. За один шаг плот может сдвигаться на одну клетку по горизонтали или вертикали. Плот и остров не могут иметь общих клеток. Требуется определить минимальное число шагов, необходимых для того, чтобы плот достиг правого нижнего угла озера. Ввод из файла INPUT.TXT. В первой строке содержатся числа N и M, разделенные пробелами. В следующих N строках находится матрица, представляющая озеро, по N подряд идущих символов в строке. Подматрица размером M M, находящаяся в левом верхнем углу, не содержит островов, то есть начальное положение плота всегда допустимо. Вывод: файл OUTPUT.TXT должен содержать единственное число — количество необходимых шагов. Если правого нижнего угла достичь невозможно, то в файл выводится No. 15 Пример Ввод 1 7 2 ....... ...@... ....... ..@.... ....... ....... ....@.. Вывод 1 10 Ввод 2 7 3 ....... .....@@ ......@ .@..... .@..... ....... ..@@... Вывод 2 8 Ввод 3 7 3 ....... .....@@ ......@ .@....@ .@..... ....... ..@@... Вывод 3 No 2.2. Путь коня (6) Дана шахматная доска, состоящая из N N клеток (2 ≤ N ≤ 300), несколько из них вырезано. Провести ходом коня через невырезанные клетки путь минимальной длины из одной заданной клетки в другую. Ввод из файла INPUT.TXT. В первой строке задано число N. В следующих N строках содержится по N символов. Символом # обозначена вырезанная клетка, точкой - невырезанная клетка, @ - заданные клетки (таких символов два). Вывод в файл OUTPUT.TXT. Если путь построить невозможно, вывести "Impossible", в противном случае вывести такую же карту, как и на входе, но пометить все промежуточные положения коня символом @. Примеры Ввод 1 Ввод 2 Ввод 3 5 5 5 ..... @..@. @.... .@@.. ..##. ..#.. ..... ..... .#... ..... ..... ..... ..... ..... ....@ Вывод 1 Вывод 2 Вывод 3 ...@. @..@. Impossible .@@.. ..##. ....@ .@..@ ..... ..@.. ..... @.... 2.3. Остров (10) Прямоугольный остров имеет кратеры. Требуется соединить каналами не менее двух кратеров с океаном так, чтобы общая длина каналов была минимальной. Кратером называется совокупность квадратов, удовлетворяющая таким условиям: из любого квадрата этого кратера можно попасть в любой другой квадрат этого же кратера, последовательно переходя по кратеру из квадрата в квадрат через их общую сторону; никакие два кратера не пересекаются и не касаются друг друга ни по вертикальной, ни по горизонтальной сторонам квадратов (касание кратеров углами допускается); нет кратеров на границе прямоугольника. Ввод из файла INPUT.TXT. В первой строке находятся числа N и M через пробел, далее идут N строк по M символов (3 ≤ N, M ≤ 50). Символ X обозначает территорию кратера, точка соответствует незанятой территории. Других символов в исходном файле нет. Вывод в файл OUTPUT.TXT. Вывести N строк по M знаков. Каналы показать символами '*'. Гарантируется наличие решения. Примеры Ввод 1 Вывод 1 5 7 ....... ...... 16 ....... ...... ..X.... **X... ....X.. ....X* ....... ...... Ввод 2 Вывод 2 9 13 ............. ........*.... ............. ........*.... ..XXXXX...... ..XXXXX**.... ..X..X....... ..X..X..*.... ..X.X.X.X.... ..X.X.X.X.... ..X..X....... ..X..X....... ..XXXXX...... ..XXXXX...... ............. ............. ............. ............. Подсказка. Один из способов решения: 1) поиском в глубину пометить клетки кратеров числовыми метками (разными для разных кратеров); 2) поиском в ширину (волновой алгоритм) найти два кратчайших пути от разных кратеров до края, определить их общую длину; 3) от каждой свободной клетки поиском в ширину найти кратчайший путь до границы; кратчайшие пути до двух разных кратеров и сложить их длину; 4) из двух вариантов в пунктах 2 и 3 выбрать лучший. 2.4. Найти кольцо (8) Прямоугольная комната размером M N метров с мебелью покрыта квадратными паркетными плитами со стороной один метр. В углу комнаты стоит тяжелый сейф, занимая всю площадь плиты. Под сейф закатилось кольцо с бриллиантом, поэтому решено полностью освободить плиту под сейфом. Для этого нужно переместить сейф на одну из соседних плит путем кантования поворота в плоскости пола на 90° вокруг одного из своих углов. Соседними считаются плиты, имеющие общую сторону. Некоторые плиты комнаты заняты стульями. Каждый стул может быть переставлен на свободную соседнюю с ним плиту. В комнате может быть и другая мебель. Она также занимает определенные плиты, но в отличие от стульев не может перемещаться. При повороте сейфа никакая его точка не должна пересекать внутреннюю часть такой плиты, на которой стоит стул или другая мебель. Матрица M N определяет начальное положение мебели. Каждый элемент матрицы описывает одну паркетную плиту. Сейф находится в левом верхнем углу. Плите с сейфом соответствует символ '#', свободной плите паркета - символ '.' (точка), плите со стулом - символ '@', плите с другой мебелью - символ '*'. Поворот сейфа выполняется за одну минуту, а перестановка стула - за одну секунду. Найти минимальное время в секундах, за которое сейф может быть перемещен. Ввод из файла INPUT.TXT. В первой строке содержатся числа M и N (2 M, N 300), разделенные пробелами. В следующих M строках находится матрица, описывающая комнату, по N подряд идущих символов в строке. Вывод в файл OUTPUT.TXT. Вывести наименьшее число секунд, необходимых для освобождения плиты под сейфом. Если плиту освободить невозможно, вывести No. Примеры Ввод 1 Ввод 2 Ввод 3 4 4 4 3 4 2 #... #.* #. .... .@. .@ @.@. @** @* ...@ @.@ @@ Вывод 1 Вывод 2 Вывод 3 17 60 61 No 2.5. Пчела Майа (6) Пчелы живут в ульях, где есть соты. Соты представляют собой поле правильных шестиугольников, соприкасающихся друг с другом. Правильное поле строится следующим образом: сначала имеется всего одна сота (рис. 1) – это правильное поле первого уровня; затем вокруг соты появляются соседние (рис. 2) – это правильное поле второго уровня; затем строится еще один «ободок» (рис. 3) – это правильное поле третьего уровня, и т. д. Пчела Майя возвращается в улей. Она живет в одной из сот правильного поля уровня N (2 N 20). Для того, чтобы добраться до своей соты (если она не расположена с краю поля), Майе нужно переместиться через другие соты, в которых могут жить как друзья (перемещаться можно), так и враги (перемещаться нельзя). Майя очень устала и хочет добраться до своей соты, пройдя через минимальное число других сот. Свой путь она может начинать с любой дружественной соты, находящейся с краю поля (то есть такой соты, которая не окружена со всех сторон соседними сотами). Ввод. В первой строке файла INPUT.TXT записано одно число N – уровень правильного поля. В следующих 2N-1 строках содержатся последовательности из символов ‘V’, ‘D’, ‘M’ (‘V’ – сота врага, ‘D’ – сота друга, ‘M’ – сота Майи). Вывод. В единственной строке файла OUTPUT.TXT выводится минимальное число сот, через которые придется пройти Майе, чтобы попасть в свою соту (своя сота тоже считается), или ноль, если Майе не удастся попасть в свою соту. Примеры Ввод 1 Ввод 2 Ввод 3 2 3 2 VV VVV VV VMV VDDV VMV VD VMVDV VV VVDV VVD Вывод 1 Вывод 2 Вывод 3 2 6 0 2.6. Шахматы (12) Шахматная доска состоит из N строк и M столбцов (1 ≤ N, M ≤ 15). Имеется единственный белый король. У черных в распоряжении кони, слоны и ладьи. По заданному расположению фигур требуется взять белым королем все черные фигуры за минимальное число ходов, не находясь при этом под боем. Ввод. В первой строке находятся числа M и N. В следующих N строках по M символов задано расположение фигур. Имеются следующие обозначения: «.» – пустая клетка; «*» – белый король; «K» – черный конь; «B» – черный слон; «R» – черная ладья. Белый король в начальной позиции не атакован. Общее число черных фигур не более 14. Вывод. В единственной строке выводится минимальное число ходов, необходимое для взятия черных фигур. Вывести 0, если черных фигур нет, и -1, если взять все черные фигуры невозможно. 18 Ограничения. На одном тесте время счета не должно превышать 6 сек. Максимально допустимая память 256 мгб. Пример Ввод 7 9 ......... ......... ......... ..R.K.R.. ......... ......... *........ Вывод 9 2.7. Квадратный дом (5) В квадратной комнате размером M × M дециметров расставлена квадратная мебель. Стороны каждого предмета мебели параллельны стенам комнаты. Размер каждого предмета мебели представляется целым числом дециметров, а сам предмет отстоит от стен на целое число дециметров. Так как мебель может быть разной по высоте, то одну и ту же площадь пола могут занимать несколько предметов (например, табуретки могут быть полностью или частично задвинуты под стол). Сверху комната освещена точечным источником света, расположенным очень высоко, поэтому лучи падают строго перпендикулярно полу. Имеются N предметов мебели, для каждого из которых заданы в дециметрах размер D, а также расстояния от левой стены X и от правой стены Y. Требуется написать программу, которая определяет площадь максимальной освещенной области на полу. Областью считается совокупность квадратных дециметров пола, на которые не падает тень от мебели и такой, что любой квадратный дециметр области граничит хотя бы одной своей стороной с другим квадратным дециметром этой же области (исключение составляет только область из одного квадратного дециметра). Ввод. В первой строке находятся числа N и M. Следующие N строк содержат по три целых числа D, X и Y (1 ≤ D ≤ M; 0 ≤ X, Y ≤ M - D), разделенные пробелами. Вывод. В выходной файл необходимо вывести значение P - площадь максимальной освещенной области. Примеры Ввод 1 Ввод 2 Ввод 3 6 10 1 100 8 10 3 1 2 100 0 0 3 5 4 3 7 7 4 5 0 4 0 6 2 3 0 5 5 0 3 0 0 2 4 5 5 0 4 1 2 0 3 5 7 2 8 5 Вывод 1 Вывод 2 Вывод 3 19 0 9 3. Рекуррентные соотношения Рассмотрим следующую задачу. Имеются последовательности длины N, состоящие из 0 и 1. Требуется по заданному числу N (1 N 40) определить количество таких последовательностей, в которых никакие две единицы не стоят рядом. Казалось бы, задача очевидна. При заданном N имеется 2N последовательностей из нулей и единиц. Действительно, в каждой позиции может находиться два значения, а отдельные разряды независимы. Можно перечислять последовательности и проверять с 19 помощью стандартных функций, имеются ли две единицы рядом. Останется из 2 N последовательностей вычесть число последовательностей с двумя единицами подряд. Снова обратим внимание на размерность. При N=30 значение 2N превышает миллиард. А если N еще больше? Рассмотрим другой подход к решению задачи. Обозначим через F(N) количество последовательностей с заданным свойством. Возможны два случая: на месте N стоит 0; на месте N стоит 1. В первом случае в позициях от 1 до N-1 может находиться любая последовательность без двух единиц рядом, то есть общее число последовательностей составляет F(N-1). Во втором случае на месте N-1 обязан находиться 0, иначе последовательность закончится двумя единицами подряд. А вот в позициях от 1 до N-2 может находиться любая последовательность без двух единиц рядом. Таким образом, общее число искомых последовательностей составляет F(N-2). В результате получаем формулу F(N)=F(N-1)+F(N-2), совпадающую с правилом вычисления чисел Фибоначчи. Значение функции F на любом шаге определяется через ее значения на предыдущих шагах. Такие формулы называются рекуррентными. Легко установить, что F(1)=2, F(2)=3. Поэтому F(3)=F(2)+F(1)=5, F(4)=F(3)+F(2)=8, F(5)=F(4)+F(3)=13 и т. д. Сейчас вычислений немного, но есть другая трудность. Последовательность Фибоначчи быстро растет, а результатом должно быть целое число, которое при больших N невозможно представить точно стандартными целочисленными типами данных. В таких случаях используют собственные типы данных и процедуры работы с ними. Их в совокупности называют длинной арифметикой. Мы рассмотрим эти проблемы ниже. Сформулируем еще одну похожую задачу. Сообщение. В сообщении, состоящем из одних русских букв и пробелов, каждую букву заменили её порядковым номером в русском алфавите (А - 1, Б - 2, ..., Я - 33), а пробел - нулем. Требуется по заданной последовательности цифр найти количество исходных сообщений, из которых она могла получиться. Ввод из файла INPUT.TXT. В первой строке содержится последовательность цифр. Вывод в файл OUTPUT.TXT. Вывести одно число. Ограничения: цифр не более 100, время 1 с. Пример Ввод 1025 Вывод 4 Обозначим через F(N) количество сообщений, которые можно сформировать из первых N цифр. Попытаемся выразить F(N+1) через значения этой функции на предыдущих шагах. Рассмотрим два случая: цифры на местах N и N+1 образуют двухзначное число, большее 33; цифры на местах N и N+1 образуют двухзначное число, не превышающее 33. В первом случае любое сообщение, зашифрованное первыми N цифрами, может быть дополнено буквой, код которой содержится в позиции N+1. В то же время последние две цифры не могут кодировать какую-либо букву. Значит, в этом случае F(N+1)=F(N). Во втором случае помимо этого любое сообщение, представленное первыми N-1 цифрами, может быть дополнено буквой, код которой содержится в позициях N и N+1. В этом случае F(N+1)= F(N)+ F(N-1). Очевидно, F(1)=1. Правильно считать, что F(0)=1 – пустое сообщение, которое может дополняться. Далее проблем не видно. Снова потребуется использование длинной арифметики. 20 Задачи для самостоятельного решения 3.1. Заяц (5) Имеется лестница, состоящая из N ступенек. При подъеме по лестнице заяц может прыгать на любое количество ступенек от 1 до K. Сколько у зайца способов подъема по лестнице? Ввод из файла INPUT.TXT. Единственная строка содержит целые положительные числа N и K. Вывод в файл OUTPUT.TXT. Выводится единственное число - количество способов подъема по лестнице. Ограничения: 1 ≤ K, N ≤ 35, время 1 с. Пример Ввод 3 2 Вывод 3 3.2. Что в имени твоем? (6) В алфавите племени мумба-юмба только три буквы, которые обозначаются как A, B и D. Юношам в день совершеннолетия принято давать взрослые имена, состоящие ровно из N букв. Повторение букв в имени не ограничивается. Если юноша не может представить вождю скальп врага, то в имени присутствует подстрока BAD (возможно, в нескольких экземплярах), иначе такие имена категорически запрещаются. Сколько разных имен может быть в племени мумбаюмба для юношей, запоздавших в развитии (не представивших скальп)? Ввод из файла input.txt. Единственная строка содержит целое положительное число N. Вывод в файл OUTPUT.TXT. Выводится единственное число - количество имен длины N, содержащих подстроку BAD. Ограничения: 1 ≤ N ≤ 35, время 1 с. Пример Ввод 8 Вывод 1404 3.3. Числа (6) Решая задачу по информатике, Вова в очередной раз допустил ошибку. Он снова вывел в выходной файл числа, забыв разделить их пробелами. Увидев полученный результат, Вова сначала огорчился, а потом задумался над следующим вопросом: сколько существует различных последовательностей неотрицательных целых чисел, таких что, если выписать их без пробелов, то получится тот же результат, что и у него. Он вспомнил также, что его программа смогла вывести не произвольные числа, а только те, что не превосходят C и не имеют ведущих нулей. Чтобы ответить на поставленный вопрос, Вова решил написать программу, которая позволит ему найти число различных последовательностей неотрицательных целых чисел, в каждой из которых любое число не превосходит C. Он понимал, что такое число могло быть достаточно большим, поэтому ограничился поиском только последних k цифр этого числа. Написать программу, которая покажет Вове, как можно правильно решить поставленную им задачу. Ввод. Первая строка входного файла содержит три целых числа — n, C и k (1 ≤ n ≤ 50000, 1 ≤ C ≤ 108, 1 ≤ k ≤ 18). Во второй строке этого файла содержится результат работы Вовиной программы, состоящий из n цифр. Вывод. Выводится последние k цифр количества последовательностей без ведущих нулей. Примеры Ввод 1 Ввод 2 Ввод 3 3 11 2 183 10 9 1 111 9 0123456789876543210 Вывод 1 Вывод 2 Вывод 3 3 0 0 21 3.4. K-ичные числа (5) Найти количество натуральных N-значных (1 ≤ N ≤ 20) чисел в системе счисления с основанием K (2 ≤ K ≤ 8), таких, что их запись не содержит двух подряд идущих нулей. Ввод из файла INPUT.TXT. В единственной строке содержатся числа N и K в десятичной записи, разделенные пробелом. Вывод в файл OUTPUT.TXT. Программа должна выдать искомое число в десятичной записи. Пример Ввод 2 4 Вывод 12 3.5. Распил бруса (7) На пилораму привезли брус длиной L метров. Известны места, в которых необходимо сделать распилы. Стоимость одного распила равна длине распиливаемого бруса. Различный порядок распилов приводит к различным итоговым ценам. Например, брус длиной 10 метров, который нужно распилить на расстоянии 2, 4 и 7 метров можно пилить разными способами. Можно распилить сначала на отметке 2, потом 4 и потом 7. Стоимость будет 10+8+6=24. А если сначала распилить на отметке 4, потом 2 и затем 7, то стоимость составит 10+4+6=20. Требуется написать программу, которая определяла бы минимальную стоимость распила. Ввод из файла INPUT.TXT. В первой строке содержатся через пробел натуральные числа L и N (1 ≤ L ≤ 50, N < L) – длина бруса и число разрезов. Вторая строка содержит N натуральных чисел Ci (0<Ci<L ) через пробел, задающих в строго возрастающем порядке места, в которых нужно сделать распилы. Вывод в файл OUTPUT.TXT.. В единственной строке вывести минимальную стоимость распилов. Примеры Ввод 1 Ввод 2 10 2 10 4 2 7 4 5 7 8 Вывод 1 Вывод 2 17 22 3.6. Суперсчастливые билеты (8) Известно, что «счастливым» билетом называется билет, в номере которого сумма цифр первой половины номера равна сумме цифр второй половины номера. А «суперсчастливым» называется билет, у которого кроме упомянутого условия каждая цифра отличается от соседней не более чем на 1 (например, 323233) . Номер может начинаться с 0. Найти количество «суперсчастливых» номеров среди всех 2N-значных билетов (1 ≤ N ≤ 11). Ввод. Единственная строка содержит значение N. Вывод. Единственная строка содержит количество номеров. Примеры Ввод 1 Ввод 2 3 4 Вывод 1 Вывод 2 220 1296 3.7. Эксперимент (6) Результат эксперимента представляет собой себя матрицу из 1 ≤ N ≤ 500 строк и 1 ≤ M ≤ 800 столбцов, заполненную целыми числами, по модулю не превосходящими 103. Отвечающим условиям эксперимента считаются такие подматрицы размера K строк и L столбцов (0 < K < N, 0 < L < M), что сумма элементов в каждой из них в точности равна заданному числу S. Определить, сколько подматриц в исходной матрице отвечают условиям эксперимента. Ввод. В первой строке файла INPUT.TXT находятся 5 чисел N, M, K, L и S, разделенных пробелами. В каждой из следующих N строк находятся через пробел по M чисел, являющихся элементами матрицы. 22 Вывод. В первой строке файла OUTPUT.TXT вывести единственное число – количество подматриц размера K×L, сумма элементов в которых равна S. Пример Ввод 3 3 2 2 4 1 1 1 1 1 1 1 1 1 Вывод 4 3.8. Школа танцев (7) В школу бальных танцев профессора Падеграса записались N учеников — мальчиков и девочек. Профессор построил их в один ряд, и хочет отобрать из них для первого занятия группу стоящих подряд учеников, в которой количество мальчиков и девочек одинаково. Сколько вариантов выбора есть у профессора? Ввод. В первой строке входного файла задано число n (1 ≤ N ≤ 106). Во второй строке задается описание построенного ряда из мальчиков и девочек — строка из N символов a и b (символ a соответствует девочке, а символ b — мальчику). Вывод. В единственной строке выходного файла должно содержаться количество вариантов выбора требуемой группы. Примеры Ввод 1 Ввод 2 3 8 bab abbababa Вывод 1 Вывод 2 2 13