Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
mybook11.05.12.doc
Скачиваний:
8
Добавлен:
01.07.2025
Размер:
6.22 Mб
Скачать

Задача 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. Ладья бьет все клетки горизонтали и вертикали, проходящих через клетку, где она стоит, до первой встретившейся фигуры. Офицер бьет все клетки обеих диагоналей, проходящих через клетку, где он стоит, до первой встретившейся фигуры.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]