Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
37075.rtf
Скачиваний:
5
Добавлен:
13.08.2019
Размер:
982.76 Кб
Скачать

Использование структур стек и очередь при решении задач

Приведу несколько задач с решениями, которые можно дать учащимся после объяснения материала по этим темам. Решения привожу для самоконтроля. Все программы действующие.

Задача 1. «Грядки». Садовый участок разбит на квадратные клетки со стороной 1 метр и имеет размер М*N метров. На участке вскопаны грядки, представляющие собой прямоугольные конфигурации, не соприкасающиеся ни по вертикали, ни по горизонтали. Определить общее количество грядок и количество квадратных грядок. Грядки, совпадающие по диагонали, считаются разными грядками.

Структура очередь.

Program Gryadki;

{uses crt; }

const max = 100;

type

p = array[1..2,1..max] of shortint;

var

m,n,i,j,x,y:integer;

w,c,d,l,k,s:integer;

f,kvadr,kol:byte;

a:array[1..10,1..10] of shortint;

q:p;

Procedure Pusto(var q:p;var c,d:integer);

begin

c:=1; d:=1;

end;

Function Prover(var q:p;var c,d:integer):boolean;

begin

if c=d then Prover:=true else Prover:=false;

End;

Procedure Dobav(var q:p;var c,d:integer; var s:integer;

var a,b:integer);

begin

if d>max then begin s:=0; exit; end;

q[1,d]:=a; q[2,d]:=b;

d:=d+1;

s:=1; {добавили успешно}

End;

Procedure Udalen(var q:p;var c,d:integer; var s:integer);

begin

if Prover(q,c,d) then begin s:=0; exit; end;

c:=c+1;

s:=2; {удаление прошло успешно}

End;

BEGIN {clrscr;}

kol:=0;

write('m='); readln(m);

write('n='); readln(n);

writeln('если в этой позиции грядки нет - (-1), иначе - 0');

for i:=1 to m do

for j:=1 to n do begin

write('a[',i,';',j,']=');

readln(a[i,j]); end;

Pusto(q,c,d);

k:=0; {номер грядки}

f or i:=1 to m do

for j:=1 to n do

if a[i,j]=0 then begin

kvadr:=0;

k:=k+1;

Dobav(q,c,d,s,i,j);

a[i,j]:=k;

kvadr:=kvadr+1;

while c<>d do

for l:=c to d do begin

x:=q[1,l]; y:=q[2,l];

if (x>1) and (a[x-1,y]=0) then begin w:=x-1;

Dobav(q,c,d,s,w,y);

a[w,y]:=k;

kvadr:=kvadr+1;

end;

if (x<m) and (a[x+1,y]=0) then begin w:=x+1;

Dobav(q,c,d,s,w,y);

a[x+1,y]:=k;

kvadr:=kvadr+1;

end;

if (y>1) and (a[x,y-1]=0) then begin w:=y-1;

Dobav(q,c,d,s,x,w);

a[x,y-1]:=k;

kvadr:=kvadr+1;

end;

if (y<n) and (a[x,y+1]=0) then begin w:=y+1;

Dobav(q,c,d,s,x,w);

a[x,y+1]:=k;

kvadr:=kvadr+1;

end;

Udalen(q,c,d,s);

end;

if sqrt(kvadr)=round(sqrt(kvadr))

t hen begin f:=1;

for w:=i to i+round(sqrt(kvadr))-1 do

for l:=j to j+round(sqrt(kvadr))-1 do

if a[i,j]<>a[w,l] then f:=2;

if f=1 then kol:=kol+1;

end; end;

writeln('Количество грядок k=',k);

writeln('Количество квадратных грядок ',kol);

readln;

END.

Задача 2. «Шахматы». Имеется шахматная доска. Некоторые поля на ней заняты белыми и черными фигурами и пешками. Каждое занятое поле белыми фигурами и пешками определяется числом –1, черными фигурами определяется числом 1. Необходимо определить маршрут белого коня с поля (Хн,Ун) на поле (Хк,Ук), при котором количество ходов минимально. Сбивание черной фигуры или пешки считается как два хода.

Структура очередь.

program Kon;

{uses crt;}

const max=100;

type p=array[1..3,1..max] of shortint;

var

m,n,i,j,x,y,z,nx,ny,kx,ky:integer;

w1,w,c,d,k,s,h,l:integer;

a:array[1..10,1..10] of shortint;

q,v:p;

Procedure Pusto(var q:p;var c,d:integer);

begin

c:=1; d:=1;

end;

Function Prover(var q:p;var c,d:integer):boolean;

begin

if c=d then Prover:=true else Prover:=false;

end;

Procedure Dobav(var q:p;var c,d:integer; var s:integer; var a,b,e:integer);

begin

if d>max then begin s:=0; exit; end;

q[1,d]:=a; q[2,d]:=b;

q[3,d]:=e;

d:=d+1;

s:=1;

End;

Procedure Udalen(var q:p;var c,d:integer; var s:integer);

begin

if Prover(q,c,d) then begin s:=0; exit; end;

c:=c+1; s:=2;

End;

BEGIN

{clrscr;}

write('m='); readln(m);

write('n='); readln(n);

writeln('Введите значения клеток:0-свободная,1-с чёрной фигурой,-1-с белой фигурой');

for i:=1 to m do

for j:=1 to n do begin

write('a[',i,',',j,']=');

readln(a[i,j]); end;

write('nx=');readln(nx);

write('ny=');readln(ny);

if a[nx,ny]<>0 then begin writeln('Конь не будет начинать свой путь в занятой клетке!'); readln; exit; end;

write('kx=');readln(kx);

write('ky=');readln(ky);

if a[kx,ky]=-1 then begin writeln('Конь не будет заканчивать свой путь в занятой белой фигурой клетке!'); readln; exit; end;

Pusto(q,c,d);

l:=0;

Dobav(q,c,d,s,nx,ny,l);

a[nx,ny]:=-1;

z :=0;

while c<>d do begin

x:=q[1,c];

y:=q[2,c];

l:=m*n;

for i:=1 to d-1 do

if (q[1,i]=x) and (q[2,i]=y) then

if l>q[3,i] then l:=q[3,i];

a[x,y]:=-1;

q[3,c]:=l;

h:=q[3,c];

if (x>1) and (y>2) and (a[x-1,y-2]<>-1)

then begin

w:=x-1;

w1:=y-2;

if a[x-1,y-2]=1 then k:=h+2 else k:=h+1;

Dobav(q,c,d,s,w,w1,k);

end;

if (x>2) and (y>1) and (a[x-2,y-1]<>-1)

then begin

w:=x-2;

w1:=y-1;

if a[x-2,y-1]=1 then k:=h+2 else k:=h+1;

Dobav(q,c,d,s,w,w1,k);

end;

if (x<m) and (y<n-1) and (a[x+1,y+2]<>-1)

then begin

w:=x+1;

w1:=y+2;

if a[x+1,y+2]=1 then k:=h+2 else k:=h+1;

Dobav(q,c,d,s,w,w1,k);

end;

if (x<m-1) and (y<n) and (a[x+2,y+1]<>-1)

then begin

w:=x+2;

w1:=y+1;

if a[x+2,y+1]=1 then k:=h+2 else k:=h+1;

Dobav(q,c,d,s,w,w1,k);

end;

if (x>1) and (y<n-1) and (a[x-1,y+2]<>-1)

then begin

w:=x-1;

w1:=y+2;

if a[x-1,y+2]=1 then k:=h+2 else k:=h+1;

Dobav(q,c,d,s,w,w1,k);

end;

if (x>2) and (y<n) and (a[x-2,y+1]<>-1)

then begin

w:=x-2;

w1:=y+1;

if a[x-2,y+1]=1 then k:=h+2 else k:=h+1;

Dobav(q,c,d,s,w,w1,k);

end;

if (x<m-1) and (y>1) and (a[x+2,y-1]<>-1)

then begin

w:=x+2;

w1:=y-1;

if a[x+2,y-1]=1 then k:=h+2 else k:=h+1;

Dobav(q,c,d,s,w,w1,k);

end;

if (x<m) and (y>2) and (a[x+1,y-2]<>-1)

then begin

w:=x+1;

w1:=y-2;

if a[x+1,y-2]=1 then k:=h+2 else k:=h+1;

Dobav(q,c,d,s,w,w1,k);

end;

Udalen(q,c,d,s);

l:=m*n;

for i:=1 to d-1 do

if (q[1,i]=kx) and (q[2,i]=ky) then begin

z:=1;

if l>q[3,i] then l:=q[3,i];

end;

end;

if z<>0 then writeln(l,' шаг(-ов,-а)') else writeln('Такого пути нет!');

{ for i:=1 to 3 do begin

for j:=1 to d-1 do

write(q[i,j]:3);

writeln; end;}

readln;

END.

Задача 3. Баланс скобок.

1. В строке расположена последовательность символов. Среди символов имеются символы скобки [({,})], расставленные с соблюдением баланса. Необходимо записать в новой строке все символы, расположенные вне скобок, а затем в обратном порядке символы, заключенные в скобки.

Пример: Исходная информация – ABC{D(E)F}KLM{Z[H]O}BN

Результирующая строка – ABCKLMBNOHZFED

Для хранения символов, заключенных в скобки, использовать структуру данных стек.

Примечание: Скобки могут быть вложенными. ASD{G{H[(J)K]}VB}XCV. Для отслеживания скобок использовать стек.

program Skobki;

const

max=20;

type

stack=array[1..max] of char;

var

x:char;

v,t,p:string;

s:stack;

k,d,i,c,vs:integer;

Procedure Pusto(var s:stack;var vs:integer);

begin

vs:=0;

End;

Function Prover(vs:integer):boolean;

Begin

if vs=0 then Prover:=true else Prover:=false;

End;

Procedure Dobav(var s:stack;var vs:integer; var c:integer;

var x:char);

Begin

if vs=max then begin c:=0; exit; end;

vs:=vs+1;

s[vs]:=x;

c:=1;

End;

Procedure Udal(var s:stack;var vs:integer; var c:integer;

var x:char);

Begin

if Prover(vs) then begin c:=0; exit; end;

x:=s[vs];

vs:=vs-1;

c:=0;

End;

BEGIN

Pusto(s,vs);

writeln('Введите выражение со скобками');

readln(p);

d :=length(p);

i:=1;

k:=0;

while i<=d do begin

x:=p[i];

case x of

'(','[','{':begin Dobav(s,vs,c,x); k:=k+1 end;

')':begin Dobav(s,vs,c,x); k:=k-1 end;

']':begin Dobav(s,vs,c,x); k:=k-1 end;

'}':begin Dobav(s,vs,c,x); k:=k-1 end;

'A'..'Z':if k=0 then v:=v+x else Dobav(s,vs,c,x);

end;

i:=i+1;

end;

while vs<>0 do begin

case s[vs] of

'A'..'Z':v:=v+s[vs];

end;

vs:=vs-1;

end;

writeln('Полученное выражение ',v);

readln;

End.

Задача 4.Корректировка текста

В строке-предложении со стандартным набором разделителей между словами (' ',:; -) встречается корректирующий символ *. Предложение заканчивается точкой. Если он встречается четное количество раз, то из строки удаляется аналогичное количество предшествующих ему символов; если он встречается нечетное количество раз, то из строки удаляется предшествующее им аналогичное количество слов. Скорректировать строку и вывести ее в обратном порядке.

program predl;

const

max=100;

type

stack=array[1..max] of char;

var

x,x1:char;

v,p:string;

g,s:stack;

k,d,i,j,c,vs:integer;

Procedure Pusto(var s:stack;var vs:integer);

begin

vs:=0

End;

Function Prover(vs:integer):boolean;

Begin

if vs=0 then Prover:=true else Prover:=false

End;

Procedure Dobav(var s:stack;var vs:integer; var c:integer;

var x:char);

Begin

if vs=max then begin c:=0; exit end;

vs:=vs+1;

s[vs]:=x;

c:=1

End;

Procedure Udal(var s:stack;var vs:integer; var c:integer;

var x:char);

Begin

if Prover(vs) then begin c:=0; exit end;

x:=s[vs];

vs:=vs-1;

c:=0

End;

BEGIN

Pusto(s,vs);

writeln('Введите предложение, где могут встречаться знаки * один или несколько раз:');

readln(p);

d:=length(p);

i :=1;

k:=0;

while i<=d do

begin

x:=p[i];

case x of

'*': k:=k+1;

else

if k mod 2=0 then begin

for j:=1 to k do

Udal(s,vs,c,x1);

Dobav(s,vs,c,x);

k:=0

end

else begin

for j:=1 to k do begin

Udal(s,vs,c,x1);

while (x1<>' ') and (x1<>'-') and

(x1<>',') and (x1<>';') and

(x1<>':') do

Udal(s,vs,c,x1);

Dobav(s,vs,c,x1);

Dobav(s,vs,c,x) end;

k:=0

end

end;

i:=i+1

end;

for i:=vs downto 1 do

v:=v+s[i];

writeln(v);

readln

END.

Задача 5. Чередование

В строке расположена последовательность символов, являющихся буквами английского алфавита. Записать в новой строке символы исходной строки, чередуя по очереди гласные и согласные буквы. Оставшиеся буквы дописать в конец строки. Для решения использовать стек.

program glasn_soglasn;

const

max=20;

type

stack=array[1..max] of char;

var

x:char;

v,p:string;

g,s:stack;

d,i,c,vs,vg:integer;

Procedure Pusto(var s:stack;var vs:integer);

begin

vs:=0

End;

Function Prover(vs:integer):boolean;

Begin

if vs=0 then Prover:=true else Prover:=false

End;

Procedure Dobav(var s:stack;var vs:integer; var c:integer;

var x:char);

Begin

if vs=max then begin c:=0; exit end;

vs:=vs+1;

s[vs]:=x;

c:=1

End;

Procedure Udal(var s:stack;var vs:integer; var c:integer;

var x:char);

Begin

if Prover(vs) then begin c:=0; exit end;

x:=s[vs];

vs:=vs-1;

c:=0

E nd;

BEGIN

Pusto(s,vs);

Pusto(g,vg);

writeln('Введите строку, состоящую из больших латинских букв');

readln(p);

d:=length(p);

i:=1;

while i<=d do

begin

x:=p[i];

case x of

'A','E','I','O','U','Y': Dobav(g,vg,c,x)

else Dobav(s,vs,c,x)

end;

i:=i+1

end;

v:='';

if vs>vg then i:=vg else i:=vs;

for d:=1 to i do

v:=v+g[d]+s[d];

if i=vg then

for d:=vg+1 to vs do

v:=v+s[d]

else

for d:=vs+1 to vg do

v:=v+g[d];

writeln(v);

readln

END.

Задача 6. Ищу путь

Имеется лабиринт, представленный матрицей размером N*M, где 0 означает проходимая клетка, а 1 – непроходимая клетка. Найти выход из лабиринта, используя стратегию «держусь за стенку» (конечной клеткой может быть любая крайняя клетка матрицы). В решении использовать стек.

program labirint;

const

max=100;

type

stack=array[1..2,1..max] of integer;

var

a:array[1..20,1..20] of byte;

s:stack;

k,xn,yn,n,m,i,j,c,vs:integer;

Procedure Pusto(var s:stack;var vs:integer);

begin

vs:=0

End;

Function Prover(vs:integer):boolean;

Begin

if vs=0 then Prover:=true else Prover:=false

End;

Procedure Dobav(var s:stack;var vs:integer; var c:integer;

var x,y:integer);

Begin

if vs=max then begin c:=0; exit end;

vs:=vs+1;

s[1,vs]:=x;

s[2,vs]:=y;

c:=1

End;

Procedure Udal(var s:stack;var vs:integer; var c:integer);

Begin

if Prover(vs) then begin c:=0; exit end;

vs:=vs-1;

c:=0

End;

BEGIN

Pusto(s,vs);

write('n=');readln(n);

write('m=');readln(m);

for i:=1 to n do

for j:=1 to m do begin

write('a[',i,',',j,']=');

readln(a[i,j]) end;

write('Введите xn, не вводить 1 и значение n ');readln(xn);

write('Введите yn, не вводить 1 и значение m ');readln(yn);

i :=xn;

j:=yn;

k:=1;

while (i<>1) and (i<>n) and (j<1) and (j<>m) do

case k of

1:if (a[i,j-1]=1) and (a[i+1,j]=0) then begin

i:=i+1;

Dobav(s,vs,c,i,j)

end

else if a[i,j-1]=0 then

begin

j:=j-1;

Dobav(s,vs,c,i,j);

k:=4

end

else

k:=2;

2:if (a[i+1,j]=1) and (a[i,j+1]=0) then begin

j:=j+1;

Dobav(s,vs,c,i,j)

end

else if a[i+1,j]=0 then

b egin

i:=i+1;

Dobav(s,vs,c,i,j);

k:=1

end

else

k:=3;

3:if (a[i,j+1]=1) and (a[i-1,j]=0) then begin

i:=i-1;

Dobav(s,vs,c,i,j)

end

else if a[i,j+1]=0 then

b egin

j:=j+1;

Dobav(s,vs,c,i,j);

k:=2

end

else

k:=4;

4:if (a[i,j-1]=0) and (a[i-1,j]=1) then begin

j:=j-1;

Dobav(s,vs,c,i,j)

end

else if a[i-1,j]=0 then

begin

i:=i-1;

Dobav(s,vs,c,i,j);

k:=3

end

else

k:=1

end;

Writeln('Координаты пути:');

for i:=1 to 2 do begin

for j:=1 to vs do

write(s[i,j]:3);

writeln

end;

readln

END.

readln

END.

Задача 7. «Кладоискатель». Лабиринт задается матрицей 10*10, элементы которой равны 1 или 0. Клетка считается проходимой, если она содержит 0 и непроходимой, если она содержит 1. Начальное положение кладоискателя задается координатами одной из крайних клеток. Кладоискатель может перемещаться из одной проходимой клетки в другую, если они имеют общую сторону. Составить программу поиска и вывода кратчайшего пути кладоискателя. Местонахождение клада задается координатами одной из проходимых клеток. (На мой взгляд, это задача про робота из раздела очереди. Только в той задаче добровольно, для удобства, был выведен маршрут робота, а тут его надо найти обязательно.)

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