- •Оценка эффективности алгоритмов
- •Целочисленная арифметика
- •Дано натуральное число. Выяснить является ли оно палиндромом, то есть читается справа налево и слева направо одинаково
- •Дано натуральное число. Выяснить соотношение между количествами двоек и пятерок в этом числе
- •Найти самую большую и самую маленькую цифры данного натурального числа
- •Выяснить образуют ли цифры натурального числа возрастающую последовательность
- •Формат входного файла
- •Формат выходного файла
- •Формат входного файла
- •Формат выходного файла
- •Формат входного файла
- •Формат выходного файла
- •Длинная арифметика
- •Выходные данные
- •Задачи Задача 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)
- •Формат входного файла
Задача 5 Малыш играет в "Морской бой 2" Малыш играет в "Морской бой". Поле для игры представляет собой квадрат
N x N клеток (2<=N<=100). На поле отмечены клетки, в которые Малыш уже стрелял. Однако пока он не попал ни в один корабль противника. Требуется определить максимальную длину корабля, который может поместиться в небитых клетках этого поля. Корабль представляет из себя объединение квадратиков ширины 1, расположенных на одной диагонали и последовательно сцепленных вершинами.. (Гарантируется, что на поле есть хотя бы одна небитая клетка.)
Входные данные:
Входной файл содержит в первой строке натуральное число N –размеры поля.
В последующих N строках по N чисел в каждой. Числа разделены пробелами. Число 1 означает, что в соответствующую клетку стреляли, число 0 – что в клетку не стреляли.
Выходные данные:
вывести одно число от 1 до N – максимальную возможную длину корабля.
Пример
-
Input.txt
Output.txt
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
9
В решении используем закон программирования : выигрываем в памяти, проигрываем во времени.
Вместо двух массивов будем использовать только один масив b. Но тогда по массиву a придется пробежаться дважды.
program malish;
const nmax=100;
Var
a,b:array[0..nmax+1,0..nmax+1] of byte;
i,j,n,max:byte;
Begin
assign(input,'input.txt'); reset(input);
assign(output,'output.txt'); rewrite(output);
fillchar(a,sizeof(a),0); fillchar(b,sizeof(b),0);
read(n);
for i:=1 to n do
for j:=1 to n do
read(a[i,j]);
max:=0;
for i:=1 to n do
for j:=1 to n do
if a[i,j]=0 если a[i,j]=0, то длина корабля увеличится на 1
then
begin
b[i,j]:=b[i-1,j-1]+1;
if max<b[i,j] then max:=b[i,j];
end;
fillchar(b,sizeof(b),0);
for i:=1 to n do
for j:=1 to n do
if a[i,j]=0 если a[i,j]=0, то длина корабля увеличится на 1
then
begin
b[i,j]:=b[i-1,j+1]+1;
if max<b[i,j] then max:=b[i,j];
end;
write(max);
close(output);
End.
задачина2массивы
Задача 6 Площадь острова 1 (решение с использованием двух очередей)
Найти площадь острова составленного из 1 в матрице размера N*M. Квадратики из 1 имеют общую сторону.
Входной файл Input.txt содержит:
В первой строке два целых числа - размер матрицы: n и m (1<=n,m<=100);
В последующих n строках карту. В каждой строке m нулей и единиц, разделенных пробелом.
Выходной файл Output.txt содержит:
площадь острова.
Input.txt |
Output.txt |
3 4 0 0 0 0 0 0 1 0 1 1 1 1 |
5 |
Сразу ясно, что количество единиц в матрице и есть площадь острова. Достаточно их пересчитать и, задача решена. Но мы поступим по-другому. Нам нужно универсальное решение и, если островов будет несколько, то первое решение не проходит. Будем использовать две очереди старую и новую. Находим сначала первую единицу, принадлежащую острову. Для этого бежим по строкам матрицы. Найденную единицу помещаем в старую очередь. Начальное количество элементов в старой очереди равно одному. Перебираем элементы старой очереди и для каждого проверяем соседние четыре клетки. Если в соседней клетке находится единица, то она принадлежит острову и мы считаем ее и помещаем в новую очередь. Затем новую очередь делаем старой и процесс повторяется до тех пор пока в новой очередь не станет пустой. Чтобы не считать единицы во второй раз рассмотренные единицы заменяются нулями. Мы как бы топим остров.
Процесс похож на заражение вирусом соседних клеток. Вирус заражает соседние, те в свою очередь своих соседей и так далее. Индексы клеток будут следующие:
const nmax=100;mmax=100;
di:array[1..4] of integer=(-1,0,1,0); приращения индексов клеток
dj:array[1..4] of integer=(0,1,0,-1);
var s,kolnew,kolold,t,i,j,i0,j0,n,m:integer;
old,new: array[1..2,1..2*(nmax+mmax)] of byte; две очереди старая и новая
a:array[0..nmax+1,0..nmax+1] of byte; карта моря с островом
procedure init;
begin
assign(input,'input.txt'); reset(input);
read(n,m);
fillchar(a,sizeof(a),0); окружаем матрицу нулями
for i:=1 to n do считываем матрицу
for j:=1 to m do
read(a[i,j]);
close(input);
end;
function poisk(var i1,j1:integer):boolean; ищем 1
var i,j:integer;
begin
poisk:=false;
for i:=1 to n do
for j:=1 to n do
if a[i,j]=1 если нашли 1
then begin i1:=i;j1:=j;poisk:=true;exit end; запоминаем ее координаты
end;
procedure out; вывод результата
begin
assign(output,'output.txt'); rewrite(output);
write(s);
close(output);
end;
procedure solve;
begin
if poisk(i0,j0) если остров есть
then
begin
s:=1;kolold:=1;
old[1,1]:=i0;old[2,1]:=j0; помещаем найденную 1 в очередь
a[i0,j0]:=0; топим ее
repeat повторяем до тех пор пока в новой
очереди есть элементы
fillchar(new,sizeof(new),0);kolnew:=0; очищаем новую очередь
for j:=1 to kolold do бежим по старой очереди
for t:=1 to 4 do проверяем 4 соседей
begin
i0:=old[1,j]+di[t];
j0:=old[2,j]+dj[t];
if a[i0,j0]=1 если в соседней клетке 1
then
begin
a[i0,j0]:=0; топим ее
inc(kolnew); считаем
inc(s); добавляем 1 в площадь
new[1,kolnew]:=i0;
new[2,kolnew]:=j0; заносим в новую очередь
end;
end;
kolold:= kolnew; новую очередь делаем старой
old:=new;
until kolnew=0;
end;
end;
begin init; solve; out; end.
Иногда в задачах такого типа встречается вариант задания карты, в которой нули и единицы не разделяются пробелом. В этом случае меняется процедура считывания карты. Она будет следующей.
procedure init;
begin
assign(input,'input.txt');
reset(input);
read(n);readln(m); считываем размеры матрицы
fillchar(a,sizeof(a),0); окружаем матрицу нулями
for i:=1 to n do считываем матрицу
begin
for j:=1 to m do
begin
read(c); считываем очередное изображение цифры
val(c,a[i,j],cod); преобразуем его в цифру и помещаем в
массив
end;
readln; переводим курсор на новую строку
end;
close(input);
end;
Где переменная с будет символьного типа char;
задачина2массивы
Задача 7 Площадь острова 2 (Обход в глубину)
Карта моря задана матрицей размера n*m состоящей из квадратиков, в которых записаны 0 или 1. 0 –это вода,1-суша. Два квадратика с 1 принадлежат одному острову, если они имеют общую сторону. Найти площадь острова.
Входной файл Input.txt содержит:
В первой строке два целых числа - размер матрицы: n и m (1<=n,m<=100);
В последующих n строках карту. В каждой строке m нулей и единиц, разделенных пробелом.
Выходной файл Output.txt содержит:
площадь острова.
Input.txt |
Output.txt |
3 4 0 0 0 0 0 0 1 0 1 1 1 1 |
5 |
При обходе в глубину используется рекурсия.
Program ostrov;
const nmax=10;
mmax=10;
di:array[1..4] of integer=(-1,1,0,0); приращения индексов
dj:array[1..4] of integer=( 0,0,1,-1);
var a:array[0..nmax+1,0..mmax+1] of byte; карта моря
s,i,j,n,m:integer;
i0,j0:byte;
log:boolean; если log=true, тоэто сигнал о
том, что найдена 1
procedure init;
begin
assign(input,'input.txt'); reset(input);
read(n,m);
for i:=0 to n+1 do окаймляем матрицу нулями
for j:=0 to m+1 do
a[i,j]:=0;
for i:=1 to n do
for j:=1 to m do
read(a[i,j]);
end;
procedure poisk(var i0,j0:byte); ищем 1
var i,j:integer;
begin
for i:=1 to n do
for j:=1 to m do
if a[i,j]=1
then
begin i0:=i;j0:=j;log:=true;exit end;
end;
procedure rec(i0,j0:byte); вычисление площади острова
var t:integer;
begin
a[i0,j0]:=0; топим 1
inc(s); увеличиваем площадь на 1
for t:=1 to 4 do просматриваем 4 соседние клетки
begin
if a[i0+di[t],j0+dj[t]]=1 если в соседней клетке 1
then
rec(i0+di[t],j0+dj[t]);end; то запускаем рекурсию от нее
end;
procedure out; вывод результата
begin
assign(output,'output.txt'); rewrite(output);
write(s);
close(output);
end;
procedure solve;
begin
s:=0;
log:=false;
poisk(i0,j0);
if log then rec(i0,j0);
end;
begin init; solve; out; end.
задачина2массивы
Задача 8 Площади островов 1 (решение обходом в глубину)
Карта моря задана матрицей размера n*m, состоящей из квадратиков, в которых записаны 0 или 1. 0 –это вода,1-суша. Два квадратика с единицами принадлежат одному острову, если они имеют общую сторону. Найти количество островов и площадь каждого острова. Площади островов вывести в порядке неубывания.
Входной файл Input.txt содержит:
В первой строке два целых числа n и m (1<=n,m<=100)- размеры матрицы:;
В последующих n строках карту. В каждой строке m нулей и единиц, разделенных пробелом.
Выходной файл Output.txt содержит:
В первой строке одно целое число – количество островов.
Во второй строке площади островов, выведенные в порядке неубывания.
Input.txt |
Output.txt |
3 4 0 1 1 0 0 0 0 0 1 1 1 1 |
2 2 4 |
Така как островов много, то придется программу нахождения площади острова повторять многократно. Для этого используем цикл repeat с использование переменной log в качестве сигнала о том, что остров найден.
Program ostrova;
const nmax=50;
mmax=50;
di:array[1..4] of integer=(-1,0,1,0);
dj:array[1..4] of integer=( 0,1,0,-1);
var a:array[0..nmax+1,0..mmax+1] of byte;
pl:array[1..nmax*mmax div 2] of integer;
s,i,j,n,m,kol,i0,j0:integer;
log:boolean; признак того найден остров или нет
procedure init;
begin
assign(input,'input.txt'); reset(input);
assign(output,'output.txt'); rewrite(output);
read(n,m);
fillchar(a,sizeof(a),0); окаймляем матрицу нулями
for i:=1 to n do считываем карту
for j:=1 to m do
read(a[i,j]);
end;
Procedure out;
var i:integer;
begin
assign(output,'output.txt');
кewrite(output);
writeln(kol); выводим количество и площади островов
for i:=1 to kol do
write(s[i],' ');
close(Output);
end;
procedure poisk(var i0,j0:integer); ищем остров и запоминаем координаты 1
var i,j:integer;
begin
for i:=1 to n do
for j:=1 to m do
if a[i,j]=1
then
begin i0:=i;j0:=j;log:=true;exit end;
end;
procedure rec(i0,j0:integer); вычисление площади острова
var t,i,j:integer;
begin
a[i0,j0]:=0;
inc(s);
for t:=1 to 4 do
begin
i:=i0+di[t];
j:=j0+dj[t];
if a[i,j]=1
then rec(i,j);
end;
end;
procedure sort; сортируем острова по неубыванию площадей
var i,j,p:integer;
begin
for i:=1 to kol-1 do
for j:=i+1 to kol do
if s[i]>s[j]
then
begin
p:=s[i];
s[i]:=s[j];
s[j]:=p;
end;
end;
procedure solve;
begin
z:=0;
repeat повторяем пока острова есть
s:=0;
log:=false;
poisk(i0,j0); ищем остров
if log then если нашли
begin
rec(i0,j0); находим его площадь
inc(kol);pl[kol]:=s; считаем остров и запоминаем его площадь
end;
until not log;
end;
begin init; solve; sort; out end.
задачина2массивы
Задача 9 Площади островов 2 (решение с использованием двух очередей)
Карта моря задана матрицей размера n*m, состоящей из квадратиков, в которых записаны 0 или 1. 0 –это вода,1-суша. Два квадратика с единицами принадлежат одному острову, если они имеют общую сторону. Найти количество островов и площадь каждого острова. Площади островов вывести в порядке неубывания.
Входной файл Input.txt содержит:
В первой строке два целых числа n и m (1<=n,m<=100)- размеры матрицы:;
В последующих n строках карту. В каждой строке m нулей и единиц, разделенных пробелом.
Выходной файл Output.txt содержит:
В первой строке одно число – количество островов.
Во второй строке площади островов, выведенные в порядке неубывания.
Input.txt |
Output.txt |
3 4 0 1 1 0 0 0 0 0 1 1 1 1 |
2 2 4 |
Как только площадь первого найденного острова будет посчитана, сам остров будет потоплен и, мы получим ту же самую задачу, но без одного острова. Далее просто повторяем наши предыдущие действия. Найденные площади островов запоминаем в одномерном массиве S. Когда все острова будут потоплены, сортируем массив S по неубыванию.
program sosrovov;
Const nmax=10;
di:array[1..4]of integer=(0,1,0,-1);
dj:array[1..4]of integer=(1,0,-1,0);
Var n,m,io,jo,i,j,kolnew,kolold,kol:integer;
new,old:array[1..2,1..nmax] of integer; новая и старая очереди
a:array[0..nmax+1,0..nmax+1]of integer; карта
s:array[1..nmax*nmax div 2]of integer; массив площадей островов
log:boolean; сигнал о том есть ли острова
procedure Init;
begin
assign(Input,'Input.txt'); reset(Input);
Read(n,m); считываем размеры карты
for i:=0 to n+1 do окаймляем карту нулями
for j:=0 to m+1 do
a[i,j]:=0;
for i:=1 to n do считываем карту
for j:=1 to m do
read(a[i,j]);
close(Input);
end;
Procedure out;
var i:integer;
begin
assign(Output,'Output.txt');
Rewrite(Output);
writeln(kol); выводим количество и площади островов
for i:=1 to kol do
write(s[i],' ');
close(Output);
end;
procedure Poisk(var i0,j0:integer); ищем остров
var i,j:integer;
begin
for i:=1 to n do
for j:=1 to m do
if a[i,j]=1 then если 1 найдена
begin
i0:=i; запоминаем ее координаты
j0:=j;
log:=true; сигнал о том, что остров найден
exit;
end;
end;
Procedure Solve;
var t:integer;
begin
kol:=0;
repeat повторяем пока есть острова
log:=false;
Poisk(io,jo);
if log then если остров найден
begin
inc(kol);
old[1,1]:=io; помещаем координаты острова в старую
очередь
old[2,1]:=jo;
kolold:=1; количество элементов в старой очереди
s[kol]:=1; площадь острова под номером kol равна 1
Repeat пока есть элементы в новой очереди
повторяем
fillchar(new,sizeof(new),0); очищаем новую очередь
kolnew:=0; кол-во элементов в новой очереди равно 0
for i :=1 to kolold do бежим по старой очереди
begin
a[old[1,i],old[2,i]]:=0; топим кусочек острова
for t:=1 to 4 do просматриваем 4 соседние клетки
if a[old[1,i]+di[t],old[2,i]+dj[t]]=1 если в соседней клетке 1, то
then
begin
inc(kolnew); кол-во элементов в новой очереди
увеличиваем на 1
new[1,kolnew]:=old[1,i]+di[t]; заносим клетку с 1 в новую очередь
new[2,kolnew]:=old[2,i]+dj[t];
inc(s[kol]); увеличиваем площадь острова на 1
a[old[1,i]+di[t],old[2,i]+dj[t]]:=0; топим кусочек острова
end;
end;
old:=new; новую очередь делаем старой
kolold:=kolnew;
Until kolnew=0;
end
until not log;
end;
procedure sort; сортируем острова по неубыванию
площадей
var i,j,p:integer;
begin
for i:=1 to kol-1 do
for j:=i+1 to kol do
if s[i]>s[j]
then
begin
p:=s[i];
s[i]:=s[j];
s[j]:=p;
end;
end;
begin init; solve; sort; out; end.
задачина2массивы
Задача 10 Прямоугольник или квадрат?
В двумерном массиве размера N*M есть несколько фигур, составленных из 1 и не имеющих общих точек. Все остальные элементы 0. Выяснить сколько прямоугольников и квадратов расположено в массиве.
Так как фигуры из данного массива во время просмотра мы стираем, то после считывания копируем массив а в массив b.
Program vopros;
const nmax=100;
mmax=100;
di:array[1..4] of integer=(-1,1,0,0);
dj:array[1..4] of integer=( 0,0,1,-1);
var a,b:array[0..nmax+1,0..mmax+1] of byte;
i0,j0,d,h,s,i,j,n,m,kolrec,kolkw:integer;
log:boolean;
procedure init;
begin
assign(input,'input.txt');
reset(input);
assign(output,'output.txt');
rewrite(output);
read(n,m);
fillchar(a,sizeof(a),0);
for i:=1 to n do
for j:=1 to m do
read(a[i,j]);
b:=a; делаем копию массива а
end;
procedure poisk(var i0,j0:byte); поиск первой единицы, принадлежащей фигуре
var i,j:integer;
begin
for i:=1 to n do
for j:=1 to m do
if a[i,j]=1
then
begin
i0:=i;j0:=j;log:=true;exit
end; запоминаем координаты единицы и выходим
end;
procedure rec(i0,j0:byte); рекурсивная процедура вычисления площади
var i:integer;
begin
a[i0,j0]:=0;
for i:=1 to 4 do
begin
if a[i0+di[i],j0+dj[i]]=1
then
begin
a[i0+di[i],j0+dj[i]]:=0; стираем 1
inc(s); увеличиваем площадь на 1
rec(i0+di[i],j0+dj[i]); вызываем рекурсию с соседней 1
end;
end;
end;
procedure solve;
begin
kolrec:=0;kolkw:=0;
repeat повторяем до тех пор пока есть фигуры
log:=false;
poisk(i0,j0); находим первую 1 фигуры
s:=1;
if log then если фигура найдена, вычисляем ее площадь
rec(i0,j0);
i:=i0;
j:=j0;
while b[i,j]=1 do бежим вправо, пока встречаются 1
inc(j);
d:=j-j0; вычисляем ширину будущего прямоугольника
i:=i0;
j:=j0;
while b[i,j]=1 do бежим вниз, пока встречаются 1
inc(i);
h:=i-i0; вычисляем высоту будущего прямоугольника
if (h*d=s)and(h=d) если это квадрат
then inc(kolkw) считаем его
else
if h*d=s если это прямоугольник
then inc(kolrec) считаем его
until not log;
end;
begin
init;
solve;
write(kolrec,' ',kolkw);
close(output);
end.
задачина2массивы
Задача 11 Телефонный конь 1 (с использованием двух очередей.)
Сколькими способами можно набрать семизначный телефонный номер ходом шахматного коня. Первая цифра задана. Клавиатура телефона имеет следующий вид: 1 2 3
4 5 6
7 8 9
0
Входной файл Input.txt содержит:
одну цифру –первую цифру номера
Выходной файл Output.txt содержит:
одно целое число – количество семизначных номеров.
Input.txt |
Output.txt |
4 |
168 |
Program telefon_konj;
var
new,old:array[1..200] of integer; две очереди, новая и старая
b:array[0..9] of set of 0..9; массив возможных ходов с известной цифры
n,kolnew,kolold,p:longint; элементами массива будут множества из цифр
procedure init;
begin
b[0]:=[4,6]; с цифры 0 можно сходить на 4 или 6
b[1]:=[6,8];
b[2]:=[7,9];
b[3]:=[4,8];
b[4]:=[3,9,0];
b[5]:=[];
b[6]:=[1,7,0];
b[7]:=[2,6];
b[8]:=[1,3];
b[9]:=[2,4];
assign(input,'input.txt');reset(input);
read(n); считываем первую цифру номера
close(input);
end;
procedure solve;
var i,j:integer;
begin
if n=5 если данная цифра 5
then kol:=0 то ходить некуда и таких номеров нет
else иначе
begin
fillchar(new,sizeof(new),0); очищаем новую очередь
kolold:=1; t -количество элементов в очереди.
old[1]:=n; помещаем в очередь данную цифру
for p:=1 to 6 do создаем семизначный номер
begin
kolnew:=0; количество элементов в новой очереди
for i:=1 to kolold do просматриваем все элементы старой очереди
begin
for j:=0 to 9 do
if j in b[old[i]] если на цифру j можно сходить
then
begin
inc(kolnew);
new[kolnew]:=j; считаем ее и записываем в
end; в новую очередь
end;
old:=new; новую очередь делаем старой
kolold:=kolnew;
end;
end;
end;
procedure out;
begin
assign(output,'output.txt'); rewrite(output);
write(kol);
close(output);
end;
begin init; solve; out;end.
задачина2массивы
Задача 12 Телефонный конь 2 (переборное решение)
Сколькими способами можно набрать семизначный телефонный номер ходом шахматного коня. Первая цифра задана. Клавиатура телефона имеет следующий вид: 1 2 3
4 5 6
7 8 9
0
Входной файл Input.txt содержит:
одну цифру –первую цифру номера
Выходной файл Output.txt содержит:
одно целое число – количество семизначных номеров.
Input.txt |
Output.txt |
4 |
168 |
Program telefon_konj;
var
cnow,cold:array[0..9] of longint; массивы количества новых и старых набранных номеров
b:array[0..9] of set of 0..9; массив множеств возможных ходов с цифр
n,res:longint;
procedure init;
begin
b[0]:=[4,6];
b[1]:=[6,8];
b[2]:=[7,9];
b[3]:=[4,8];
b[4]:=[3,9,0];
b[5]:=[];
b[6]:=[1,7,0];
b[7]:=[2,6];
b[8]:=[1,3];
b[9]:=[2,4];
assign(input,'input.txt'); reset(input);
read(n);
end;
procedure solve; на каждой итерации считаем количество номеров
var k,i,j:integer; для каждой цифры
begin
if n=5 then res:=0 else
begin
for i:=0 to 9 do cold[i]:=1; однозначный номер -один
for i:=0 to 9 do cnow[i]:=0;
for k:=1 to 6 do делаем шесть итераций, для получения
7-мизначного номера
begin
for i:=0 to 9 do цикл по цифрам
for j:=0 to 9 do цикл по массиву b -возможных ходов
if i in b[j] если на i сходить можно
then cnow[i]:=cnow[i]+cold[j]; находим новое количество номеров
cold:=cnow; делаем новый массив старым
fillchar(cnow,sizeof(cnow),0); очищаем новый массив
end;
res:=cold[n]; результат
end;
end;
procedure out;
begin
assign(output,'output.txt'); rewrite(output);
write(res);
close(output);
end;
begin init; solve; out;end.
задачина2массивы
Задача 13 Телефонный конь 3 (Решение обходом в глубину)
Сколькими способами можно набрать семизначный телефонный номер ходом шахматного коня. Первая цифра задана. Клавиатура телефона имеет следующий вид: 1 2 3
4 5 6
7 8 9
0
Входной файл Input.txt содержит:
одну цифру –первую цифру номера
Выходной файл Output.txt содержит:
одно целое число – количество семизначных номеров.
Input.txt |
Output.txt |
4 |
168 |
Program telefon_konj;
const n=4;m=3;
di:array[1..8] of integer=(-2,-1,1,2,2,1,-1,-2);
dj:array[1..8] of integer=(1,2,2,1,-1,-2,-2,-1);
a:array[-1..n+2,-1..m+2] of integer=((-1,-1,-1,-1,-1,-1,-1),
(-1,-1,-1,-1,-1,-1,-1),
(-1,-1,1,2,3,-1,-1),
(-1,-1,4,5,6,-1,-1),
(-1,-1,7,8,9,-1,-1),
(-1,-1,-1,0,-1,-1,-1),
(-1,-1,-1,-1,-1,-1,-1),
(-1,-1,-1,-1,-1,-1,-1));
var nachi,nachj,i,j,kol,c:longint;
procedure init;
begin
assign(input,'input.txt');reset(input);
read(c);
kol:=0;
end;
procedure rec(x,y,t:integer); это обход в глубину
var z,i,j:integer;
begin
if t=7 then begin inc(kol);exit end если номер набран, считаем его и
else возвращаемся на шаг назад
for z:=1 to 8 do иначе просматриваем возможные
begin ходы
i:=x+di[z];j:=y+dj[z];
if a[i,j]<>-1 then rec(i,j,t+1); если ход можно сделать,
end; то делаем его и увеличиваем
количество шагов
end;
procedure out;
begin
assign(output,'output.txt');rewrite(output);
write(kol);
end;
begin
init;
for i:=1 to n do находим индексы элемента, в котором
содержится начальная цифра
for j:=1 to n do
if a[i,j]=c then
begin nachi:=i;nachj:=j;end;
rec(nachi,nachj,1);
out;
end.
задачина2массивы
Задача14 Одинокий конь
На шахматной доске в клетке стоит шахматный конь. Подсчитайте количество клеток, которые находятся под боем этого коня.
Формат входных данных Входной файл содержит букву и число – координаты коня.
Формат выходных данных Выходной файл должен содержать единственное число - число клеток, в которые может попасть конь за один ход.
Пример
-
Input.txt
Output.txt
a1
2
program konj1;
const n=8;
di:array [1..8] of shortint=(1,2,2,1,-1,-2,-2,-1); массивы приращений индексов клеток
dj:array [1..8] of shortint=(-2,-1,1,2,2,1,-1,-2);
var
a:array[-1..n+2,-1..n+2]of shortint; шахматная доска
t,i,j,i0,j0,kol,cod:integer;
c:char;
begin
assign(input,'input.txt');reset(input);
assign(output,'output.txt'); rewrite(output);
for i:=-1 to 10 do окружаем доску двойным слоем из -1
for j:=-1 to 10 do
a[i,j]:=-1;
for i:=1 to 8 do заполняем доску нулями
for j:=1 to 8 do
a[i,j]:=0;
read(c);
j0:=ord(c)-ord('a')+1; вычисляем номер столбца
read(c);
val(c,i0,cod); преобразуем изображение номера
строки в число
kol:=0;
for t:=1 to 8 do пробуем пойти в 8 соседних клеток
if a[i0+di[t],j0+dj[t]]=0 если пойти можно, то считаем ход
then inc(kol);
write(kol); выводим результат
close(output);
end.
задачина2массивы
Задача15 Два коня
На шахматной доске стоят два шахматный коня. Сколько клеток под боем этих коней.
Формат входных данных Входной файл Input.txt содержит букву и число – координаты первого коня и через пробел букву и число – координаты второго коня.
Формат выходных данных Выходной файл Output.txt должен содержать единственное число - число клеток, находящихся под боем двух коней.
Пример
-
Input.txt
Output.txt
a1 с2
8
В отличие от задачи с одним конем, в этой задаче для того, чтобы не считать клетку, находящуюся под боем одновременно двух коней надо отмечать клетки, находящиеся под боем каждого коня. Для первого коня единицами, для второго двойками. Клетки, в которых с самого начала находятся кони не отмечаем.
program konj1;
const
n=8;
di:array [1..8] of shortint=(1,2,2,1,-1,-2,-2,-1); массивы приращений индексов клеток
dj:array [1..8] of shortint=(-2,-1,1,2,2,1,-1,-2);
var
a:array[-1..n+2,-1..n+2]of shortint;
t,i,j,i1,j1,i2,j2,kol,cod:integer;
c:char;
begin
assign(input,'input.txt'); reset(input);
assign(output,'output.txt'); rewrite(output);
for i:=-1 to 10 do окружаем доску двойным слоем из -1
for j:=-1 to 10 do
a[i,j]:=-1;
for i:=1 to 8 do заполняем доску нулями
for j:=1 to 8 do
a[i,j]:=0;
read(c);
j1:=ord(c)-ord('a')+1;
read(c);
val(c,i1,cod);
read(c);
read(c);
j2:=ord(c)-ord('a')+1; вычисляем номер столбца
read(c);
val(c,i2,cod); преобразуем изображение номера
строки в число
kol:=0;
for t:=1 to 8 do пробуем пойти в 8 соседних клеток
if a[i1+di[t],j1+dj[t]]=0
then
begin
inc(kol);
a[i1+di[t],j1+dj[t]]:=1;
end;
for t:=1 to 8 do пробуем пойти в 8 соседних клеток
if a[i2+di[t],j2+dj[t]]=0 если пойти можно, то считаем ход
then
begin
inc(kol);
a[i2+di[t],j2+dj[t]]:=2;
end;
write(kol);
close(output);
end.
задачина2массивы
Задача16 Ферзь и пешка
На шахматной доске стоит ферзь и пешка. Подсчитать количество клеток находящихся под боем ферзя.
Формат входных данных Входной файл Input.txt содержит букву и число – координаты ферзя и через пробел букву и число – координаты пешки.
Формат выходных данных Выходной файл Output.txt должен содержать единственное число - число клеток, находящихся под боем ферзя.
Пример
-
Input.txt
Output.txt
c2 e4
19
Для более компактной записи условий выхода из циклов окружим шахматную доску двумя рядами единиц.
Пронумеруем восемь направлений движения ферзя, начиная с направления вверх по часовой стрелке. Движение по каждому направлению программируется циклом while по условию, движемся до тех пор пока не наткнемся на единицу. Положение пешки тоже отмечаем единицей.
При движении ферзя в каком–нибудь направлении сопровождается соответствующим изменением координат ферзя. Например при движении в первом направлении координата i уменьшается, а j остается постоянной, при движении во втором направлении i уменьшается, а j увеличивается.
program ferzjandpeshka;
const n=8;
di:array [1..8] of shortint=(1,2,2,1,-1,-2,-2,-1);
dj:array [1..8] of shortint=(-2,-1,1,2,2,1,-1,-2);
var
a:array[-1..n+2,-1..n+2]of shortint;
t,i,j,i1,j1,i2,j2,kol,cod:integer;
c:char;
begin
assign(input,'input.txt'); reset(input);
assign(output,'output.txt'); rewrite(output);
for i:=-1 to 10 do
for j:=-1 to 10 do a[i,j]:=1;
for i:=1 to 8 do
for j:=1 to 8 do a[i,j]:=0;
read(c);
j1:=ord(c)-ord('a')+1;
read(c);
val(c,i1,cod);
read(c);
read(c);
j2:=ord(c)-ord('a')+1;
read(c);
val(c,i2,cod);
a[i2,j2]:=1;
kol:=0;
i:=i1;j:=j1;
dec(i);
{1} while a[i,j]<>1 do пробуем идти по восьми возможным
направлениям
begin dec(i);inc(kol) end;
i:=i1;j:=j1;
dec(i);inc(j);
{2} while a[i,j]<>1 do begin dec(i);inc(j);inc(kol) end;
i:=i1;j:=j1;
inc(j);
{3} while a[i,j]<>1 do begin inc(j);inc(kol) end;
i:=i1;j:=j1;
inc(i);inc(j);
{4} while a[i,j]<>1 do begin inc(i);inc(j);inc(kol) end;
i:=i1;j:=j1;
inc(i);
{5} while a[i,j]<>1 do begin inc(i);inc(kol) end;
i:=i1;j:=j1;
inc(i);dec(j);
{6} while a[i,j]<>1 do begin inc(i);dec(j);inc(kol) end;
i:=i1;j:=j1;
dec(j);
{7} while a[i,j]<>1 do begin dec(j);inc(kol) end;
i:=i1;j:=j1;
dec(i);dec(j);
{8} while a[i,j]<>1 do begin dec(i);dec(j);inc(kol) end;
write(kol);
close(output);
end.
задачина2массивы
Задача17 Голодный конь
На шахматной доске NxN в клетке (x1,y1) стоит голодный шахматный конь. Он хочет попасть в клетку (x2,y2), где растет вкусная шахматная трава. Какое наименьшее количество ходов он должен для этого сделать?
Формат входных данных Входной файл Input.txt содержит пять чисел: N,x1,y1,x2,y2(5 <= N <= 20, 1 <= x1,y1,x2,y2 <= N). Левая верхняя клетка доски имеет координаты (1,1), правая нижняя - (N,N).
Формат выходных данных Первая строка выходного файла Output.txt должна содержать единственное число K - наименьшее необходимое число ходов коня. В каждой из следующих K+1 строк должно быть записано 2 числа - координаты очередной клетки в пути коня.
Пример
-
Input.txt
Output.txt
5
1 1
3 1
2
1 1
2 3
3 1
В первом решении используем обход в ширину с использованием двух очередей.Путь коня будем запоминать в матрице b. Каждая клетка этой матрицы будет хранить два числа – координаты той клетки откуда пришел конь. Тогда путь коня можно вывести рекурсивно. program konjochered;
Const nmax=20;
di:array[1..8]of integer=(-2,-1,1,2, 2, 1,-1,-2);
dj:array[1..8]of integer=( 1, 2,2,1,-1,-2,-2,-1);
Type z=record запись , содержащая координаты клетки
x,y:byte;
end;
Var n,s,t,inach,jnach,ikon,jkon,i,j,kolnew,kolold,d:integer;
new,old:array[1..2,1..nmax] of integer; новая и старая очереди
a:array[-1..nmax+2,-1..nmax+2] of byte;
b:array[1..nmax,1..nmax] of z;
log:boolean;
Procedure out(i0,j0:byte); рекурсивный вывод пути коня
Begin начиная с последней клетки помещаем
if (i0=0)and(j0=0) then exit; координаты клеток в стек и потом
выводим результат,
out(b[i0,j0].x,b[i0,j0].y); извлекая из стека путь коня
в нужном порядке на подъеме из стека
writeln(i0,' ',j0);
end;
begin
assign(Input,'Input.txt'); reset(Input);
assign(Output,'Output.txt'); rewrite(Output);
read(n); считываем размеры доски
fillchar(a,sizeof(a),0); очищаем массивы
fillchar(b,sizeof(b),0);
for i:=1 to n do заполняем доску 1
for j:=1 to n do
a[i,j]:=1;
read(inach,jnach,ikon,jkon); считываем координаты начала и конца пути
old[1,1]:=inach; заносим координаты начальной клетки в
old[2,1]:=jnach; старую очередь
kolold:=1; считаем ее
s:=0;
log:=false; признак того, что мы дошли до конечной клетки
a[old[1,1],old[2,1]]:=0; отмечаем начальную клетку
b[inach,jnach].x:=0; записываем нули в матрицу пути, в начальную
клетку
b[inach,jnach].y:=0; мы ниоткуда не пришли
Repeat повторяем до тех пор пока новая очередь не пуста
fillchar(new,sizeof(new),0); очищаем новую очередь
kolnew:=0;
for i :=1 to kolold do бежим по старой очереди
begin
for t:=1 to 8 do пробуем пойти в 8 соседних клеток
if a[old[1,i]+di[t],old[2,i]+dj[t]]=1 если в клетке мы еще не были
then
begin
inc(kolnew); заносим ее в новую очередь
new[1,kolnew]:=old[1,i]+di[t];
new[2,kolnew]:=old[2,i]+dj[t];
a[old[1,i]+di[t],old[2,i]+dj[t]]:=0; отмечаем, что в ней уже были
b[old[1,i]+di[t],old[2,i]+dj[t]].x:=old[1,i]; заносим номер клетки
b[old[1,i]+di[t],old[2,i]+dj[t]].y:=old[2,i]; из которой пришли, в путь
if (old[1,i]+di[t]=ikon)and (old[2,i]+dj[t]=jkon) если дошли до конечной
then log:=true; клетки, отмечаем это
end;
end;
inc(s); считаем очередной ход
old:=new; перебрасываем новую
очередь в старую
kolold:=kolnew;
Until (kolnew=0) or log;
If not log then если пути нет, выводим -1
begin write(-1);close(output);halt(0)end;
writeln(s); выводим количество ходов
out(ikon,jkon); и сам путь
close(output);
end.
Можно написать решение с использованием обхода в глубину. Путь будем запоминать по другому. В двумерном массиве будем хранить не координаты клетки из которой пришли, а значение t, которое тоже позволяет найти клетку из которой пришли и выход за пределы массива будем проверять с помощью условия в функции good.
program konp;
{$APPTYPE CONSOLE}
uses
SysUtils;
const
di:array[1..8]of integer=(-2,-1,1,2,2,1,-1,-2); приращения индексов
dj:array[1..8]of integer=(1,2,2,1,-1,-2,-2,-1);
var
way, ans:array[1..20, 1..20]of integer;
x1,x2,y1,y2,n, i: integer;
function good(i, j:integer): boolean; проверка – можно ли пойти в клетку
begin
good:= true;
if (i < 1) or (i > n) or (j < 1) or (j > n) then
good:= false;
end;
procedure dfs(i0, j0:integer); обход в глубину
var
t:integer;
begin
for t:=1 to 8 do проверяем восемь соседних клеток
if good(i0 + di[t], j0 + dj[t]) then если в клетку пойти можно и
if (ans[i0+ di[t], j0 + dj[t]] > ans[i0, j0] + 1) then результат лучше
begin
ans[i0+ di[t], j0 + dj[t]]:= ans[i0, j0] + 1; запоминаем новый результат
way[i0 + di[t], j0 + dj[t]]:=t; запоминаем из какой клетки
пришли
dfs(i0 + di[t], j0+ dj[t]); запускаем рекурсию из текущей
клетки
end;
end;
procedure fill; заполняем массив ответов 1000,
так как худший результат не может быть больше 1000
i,j:integer;
begin
for i:=1 to n do
for j:=1 to n do
ans[i,j]:= 1000;
end;
procedure wayout(i, j:integer); ывод длины пути и самого пути
var
t:integer;
begin
if (i = x1) and (j = y1)
then begin writeln(x1,' ',y1);exit;end; выводим начальную клетку
t:= way[i,j]; значение t в конечной клетке
wayout(i - di[t], j - dj[t]); выводим путь
writeln(i,' ',j);
end;
begin
reset(input,'input.txt'); rewrite(output,'output.txt');
read(n,x1,y1,x2,y2);
fill;
ans[x1,y1]:=0;
dfs(x1, y1);
writeln(ans[x2,y2]);
wayout(x2,y2);
close(input); close(output);
end.
задачина2массивы
Задача 18 Ферзь и конь
На шахматной доске стоят ферзь и конь. Каждая фигура задана своими координатами Определите количество полей, которые находятся под боем.
Формат входных данных Входной файл Input.txt содержит четыре числа – координаты ферзя и коня, записанные через пробел
Формат выходных данных Выходной файл Output.txt должен содержать единственное число - число клеток, находящихся под боем ферзя и коня.
Пример
Input.txt |
Output.txt |
5 2 7 1 |
11 |
Program ferzjand konj;
const di:array[1..8] of integer=(-2,-1,1,2,2,1,-1,-2);
dj:array[1..8] of integer=(1,2,2,1,-1,-2,-2,-1);
var a:array[-1..10,-1..10] of integer; увеличиваем размеры доски до 10*10
i,j,xk,yk,xf,yf,x1,y1,kol:integer;
procedure init;
begin
assign(input,'inkon.txt');reset(input);
read(xk,yk,xf,yf); считываем координаты коня и ферзя
if (xk=xf)and(yk=yf) then
begin
writeln('incorrect koordinates'); halt(0);
end;
fillchar(a,sizeof(a),2); заполняем массив a двойками
for i:=1 to 8 do for j:=1 to 8 do a[i,j]:=0; шахматную доску заполняем нулями
end 222222222222
procedure solve; 222222222222
begin 220000000022
kol:=0; 220000000022
for i:=1 to 8 do 220000000022
begin 220000000022
a[xf,i]:=1; заполняем нулями 220000000022
a[i,yf]:=1; строку и столбец 220000000022
end; в которой стоит 220000000022
ферзь 220000000022
i:=xf;j:=yf; 222222222222
while (i>=1)and(j>=1) do 222222222222
begin
a[i,j]:=1;dec(i);dec(j); заполняем единицами клетки,
end; которые бьет ферзь
i:=xf;j:=yf;
while (i<=8)and(j<=8) do
begin
a[i,j]:=1;inc(i);inc(j);
end;
i:=xf;j:=yf;
while (i>=1)and(j<=8) do
begin
a[i,j]:=1;dec(i);inc(j);
end;
i:=xf;j:=yf;
while (i<=8)and(j>=1) do
begin
inc(i);dec(j);a[i,j]:=1;
end;
a[xf,yf]:=0 клетка, в которой стоит ферзь не под боем ферзя
for i:=1 to 8 do заполняем единицами клетки, которые бьет конь
begin
x1:=xk+di[i];
y1:=yk+dj[i];
if a[x1,y1]=0
then a[x1,y1]:=1;
end;
for i:=1 to 8 do считаем количество единиц на шахматной доске
for j:=1 to 8 do
if a[i,j]=1
then inc(kol);
end;
procedure out;
begin
assign(output,'output.txt');rewrite(output);
write(kol); количество клеток под боем выводим в файл
close(output);
end;
begin init; solve; out;end.
задачина2массивы
Задача 19 Два разноцветных коня
На стандартной шахматной доске(8х8) живут 2 шахматных коня: Красный и Зеленый. Обычно они беззаботно скачут по просторам доски, пощипывая шахматную травку, но сегодня особенный день: у Зеленого коня День Рождения. Зеленый конь решил отпраздновать это событие вместе с Красным. Но для осуществления этого прекрасного плана им нужно оказаться на одной клетке. Заметим, что Красный и Зеленый шахматные кони сильно отличаются от черного с белым: они ходят не по очереди, а одновременно, и если оказываются на одной клетке, никто никого не съедает. Сколько ходов им потребуется, чтобы насладиться праздником?
Формат входных данных Во входном файле Input.txt содержатся координаты коней, записанные по стандартным шахматным правилам (т.е. двумя символами - маленькая латинская буква (от a до h) и цифра (от 1 до 8), задающие столбец и строку соответственно).
Формат выходных данных Выходной файл Output.txt должен содержать наименьшее необходимое количество ходов, либо -1, если кони не смогут встретиться.
Пример
-
Input.txt
Output.txt
a1 a3
1
Хотя кони ходят одновременно, мы не можем запрограммировать эту одновременность. Наши кони будут ходить по очереди, сначала все возможные ходы первого коня, а затем второго. В клетки которые посетил первый конь будем ставить 1, а в клетки, посещенные вторым конем -2. Так как мы должны иметь информацию о фактическом положении коней , то после каждой волны ходов обоих коней мы будем очищать шахматную доску, заполняя ее нулями. И для того, чтобы конь не ходил несколько раз в одну и ту же клетку поставим условие: в клетку можно пойти, если в ней не находится номер коня.
Для того, чтобы конь не выскочил за доску, окружим ее двойным кольцом клеток и заполним клетки минус единицами.
Если второй конь при очередном ходе попадает на 1, то кони встретились и можно выводить результат.
Если хотя бы одним конем будет сделано больше 63 ходов, то кони встретиться не смогут и надо выводить -1.
program dvakonj;
Const nmax=200;
di:array[1..8] of integer= (-2,-1,1,2,2,1,-1,-2); приращения индексов
dj:array[1..8] of integer= (1,2,2,1,-1,-2,-2,-1);
Var n,t,inach,jnach,ikon,jkon,i,j,kolnew1,kolold1,kolnew2,kolold2:integer;
new1,old1,new2,old2:array[1..2,1..nmax] of byte; новые и старые очереди
a:array[-1..10,-1..10] of integer; окаймленная двойным слоем доска
c:char; символьная переменная, нужная для
считывания начального положения коней
begin
assign(Input,'Input.txt'); reset(Input);
assign(Output,'Output.txt'); rewrite(Output);
for i:=-1 to 10 do заполняем массив минус единицами
for j:=-1 to 10 do
a[i,j]:=-1;
for i:=1 to 8 do доску заполняем нулями
for j:=1 to 8 do
a[i,j]:=0;
read(c); считываем исходные данные
jnach:=ord(c)-ord('a')+1; ычисляем номера строк и столбцов
read(c); в которых находятся кони
inach:=ord(c)-ord('0');
read(c);
Read(c);
jkon:=ord(c)-ord('a')+1;
read(c);
ikon:=ord(c)-ord('0');
if (inach=ikon)and(jnach=jkon) сли кони в одной клетке
then
begin write(0);close(output);halt end; выводим ноль
old1[1,1]:=inach; заносим координаты коней в старые очереди
old1[2,1]:=jnach;
kolold1:=1;
old2[1,1]:=ikon;
old2[2,1]:=jkon;
kolold2:=1;
n:=0; количество ходов
repeat
inc(n);
for i:=1 to 8 do очищаем доску
for j:=1 to 8 do
a[i,j]:=0;
fillchar(new1,sizeof(new1),0); очищаем новые очереди
kolnew1:=0;
fillchar(new2,sizeof(new2),0);
kolnew2:=0;
for i:=1 to kolold1 do бежим по первой старой очереди
begin
for t:=1 to 8 do перебираем 8 соседних клеток,в
которые можно сходить
if a[old1[1,i]+di[t],old1[2,i]+dj[t]]<>-1 если клетка в пределах поля
then
begin
inc(kolnew1); считаем ее и
new1[1,kolnew1]:=old1[1,i]+di[t]; заносим в новую очередь
new1[2,kolnew1]:=old1[2,i]+dj[t];
a[old1[1,i]+di[t],old1[2,i]+dj[t]]:=1; в клетку ставим 1
end;
if kolnew1>63 then break; если в новой очереди больше 63
клеток, то досрочно выходим из цикла
end;
for i:=1 to kolold2 do бежим по второй очереди
begin
for t:=1 to 8 do
begin
if a[old2[1,i]+di[t],old2[2,i]+dj[t]]=1 если попали в клетку с 1, то
then
begin write(n);close(output);halt(0) end; выводим результат и выходим
if a[old2[1,i]+di[t],old2[2,i]+dj[t]]<>-1
then
begin
inc(kolnew2);
new2[1,kolnew2]:=old2[1,i]+di[t];
new2[2,kolnew2]:=old2[2,i]+dj[t];
a[old2[1,i]+di[t],old2[2,i]+dj[t]]:=2;
end;
end;
if kolnew2>64 then break;
end;
old1:=new1; новые очереди делаем старыми
kolold1:=kolnew1;
old2:=new2;
kolold2:=kolnew2;
Until (kolnew1>64) or (kolnew2>64);
write(-1);
close(output);
end.
Второе решение
Построим граф, вершиной в котором будет пара клеток доски, задающая положение коней. Ребром соединим вершины, в которые можно попасть за один ход Красного и Зеленого коня. Чтобы найти ответ к задаче, нужно найти в графе кратчайшее расстояние от вершины, соответствующей начальному положению коней на доске до любой из вершин, задающих две одинаковые клетки доски. Будем решать эту задачу поиском в ширину. Заметим, что вершину графа можно задавать одним числом A*1000+B*100+C*10+D, где A и B будут координатами первого коня на доске, а C и D - второго. Сам граф с ребрами хранить не надо. Поиск соседей вершины осуществляется аналогично первому решению, только здесь нужно будет смещать положение обоих коней одновременно. Как только мы нашли вершину, первые две цифры которой совпадают со вторыми двумя, поиск закончен, ответом будет номер шага, на котором получена эта вершина.
Задача 20 Шахматы
«Лошадью ходи!»
На шахматной доске стоит несколько офицеров и ладей. Требуется посчитать количество свободных клеток, которые не находятся под боем ни одной из фигур.
Примеры входного и выходного файлов:
Input.txt |
Output.txt |
******** *RB***** ******** ******** ******** ******** ******** ******** |
47 |
******** ******** ******** ******** ******** ******** ******** ******** |
64 |
RRRRRRRR BBBBBBBB RRRRRRRR BBBBBBBB RRRRRRRR BBBBBBBB RRRRRRRR BBBBBBB* |
0 |
Замечание для тех, кто не умеет играть в шахматы:
Шахматная доска имеет размеры 8*8. Ладья бьет все клетки горизонтали и вертикали, проходящих через клетку, где она стоит, до первой встретившейся фигуры. Офицер бьет все клетки обеих диагоналей, проходящих через клетку, где он стоит, до первой встретившейся фигуры.
