Thông Báo:
Mọi thắc mắc xin liên hệ facebook: Bá Sơn
fb.com/sonden2000
Posted by : Unknown
Tuesday, March 14, 2017
PHẦN III, LẬP TRÌNH
NÂNG CAO
CHƯƠNG I. ĐỆ QUY
1, Khái niệm
Chương trình con đệ
quy là chương trình con mà trong thân chương trình con có lời gọi chinh chương
trình con đó.
2, Hiêu đệ quy thông
qua một số ví dụ.
2.1, Tính N!
Function gt(n:byte)
: qword ;
Begin
If n=0 then
gt:= 1
Else gt:=
n*gt(n-1);
End;
Nếu khi gọi chương trình con giai thừa 4 thì nó sẽ thực hiện
như thế nào?
+ Đầu tiên chương trình con sẽ truyền giá trị cho n=4
+ Vì 4 ≠ 0 nên gt:= 4*gt(4-1); ở đây có lời gọi hàm gt(3) lúc này
nó lại truyền giá trị lên n=3.
+ Vì 3 ≠ 0 nên gt:= 3*gt(3-1); ở đây có lời gọi hàm gt(2) lúc này
nó lại truyền giá trị lên n=2.
+ Vì 2 ≠ 0 nên gt:= 2*gt(2-1); ở đây có lời gọi hàm gt(1) lúc này
nó lại truyền giá trị lên n=1.
+ Vì 1 ≠ 0 nên g:= 1*gt(1-1); ở đây có lời gọi hàm gt(0) lúc này
nó lại truyền lên giá trị n=0.
+ Vì n = 0 nên gt:= 1; Hay nói cách khác là nó trả giá trị 1
lại cho hàm. Lúc này có bao nhiêu lần gọi hàm trong chương trình con thì sẽ nhớ
và thực hiện từ dưới lên ( hay nói cách khác là nó quay lui lên).
2.2 Chương trình sau
in ra file giaithua.out có nội dung gì? Vì sao?
Const fo=’giaithua.out’;
Var n: byte;
Function gt(n:byte)
: qword ;
Begin
If n=0 then
gt:= 1
Else gt:=
n*gt(n-1);
Writeln(n);
End;
BEGIN
Assign(output,fo);
rewrite(output);
Writeln(gt(5));
Close(input); close(output);
END.
2.3 Biểu thức Zero(
nguồn bài 4 đề thi hsg Tỉnh Thanh Hóa năm 2009).
Cho một số tự nhiên N ≤ 9. Giữa các số từ 1 đến N hãy
thêm vào các dấu + và - sao cho kết quả thu được bằng 0. Hãy viết chương trình
tìm tất cả các khả năng có thể.
Dữ liệu vào: Lấy từ file văn bản ZERO.INP với một dòng ghi số N.
Dữ liệu ra: Ghi vào file văn bản có tên ZERO.OUT có cấu trúc như sau:
Dữ liệu vào: Lấy từ file văn bản ZERO.INP với một dòng ghi số N.
Dữ liệu ra: Ghi vào file văn bản có tên ZERO.OUT có cấu trúc như sau:
- Dòng đầu ghi số lượng kết quả tìm được.
- Các dòng sau mỗi dòng ghi một kết quả tìm được.
Hướng dẫn giải
Áp dụng thuật toán đệ quy quay lui để giải quyết bài toán
này, ta sẽ dùng thủ tục đệ quy Try(i). Giả sử ta đã điền các dấu’+’ và ’-’ vào
các số từ 1 đến i, bây giờ cần điền các dấu giữa i và i + 1. Ta có thể chọn một
trong ba khả năng: hoặc là điền dấu ’+’, hoặc là điền dấu ’-’, hoặc là không
điền dấu nào cả. Khi đã chọn một trong ba khả năng trên, ta tiếp tục lựa chọn
dấu để điền vào giữa i + 1 và i + 2 bằng cách gọi đệ quy Try(i+1). Ta sẽ lần
lượt duyệt tất cả các khả năng đó để tìm tất cả các nghiệm của bài toán, như
vậy bài toán sẽ không bị thiếu nghiệm.
Nếu i = N ta sẽ kiểm tra xem cách điền đó có thoả mãn kết
quả bằng 0 hay không. Để kiểm tra ta dùng thủ tục Test trong chương trình. Nếu
tổng đúng bằng 0 thì cách điền đó là một nghiệm của bài toán, ta ghi nhận nó.
Nếu i < N thì tiếp tục gọi Try(i+1). Trong chương trình ta dùng biến dem để
đếm các cách điền thoả mãn, còn mảng M kiểu string sẽ ghi nhận mọi cách điền
dấu thoả mãn yêu cầu bài toán.
CODE:
Program Zero_sum;
Type MangStr = array[1..15] of string;
Const Fi =’ZERO.INP’;
Fo =’ZERO.OUT’;
Dau : array[1..3] of string[1] = (’-’,’+’,’’);
S : array[1..9] of char =(’1’,’2’,’3’,’4’,’5’,’6’,’7’,’8’,’9’);
ChuSo = [’1’..’9’];
Var N,k,dem: byte;
D : array[2..9] of string[1];
F : Text;
St : String;
M : MangStr;
Procedure Write_out;
Var i : byte;
Begin
Assign(F,Fo); Rewrite(F);
Writeln(F,dem);
For i:= 1 to dem do writeln(F,M[i],’ = 0’);
Close(F); Halt;
End;
Procedure Read_inp;
Begin
Assign(F,Fi); Reset(F);
Read(F,N); Close(F);
If N < 3 then write_out;
End;
Function DocSo(S : String): longint;
Var M : longint;
t : byte;
Begin
M:= 0; t:= 0;
If S[k] in [’+’,’-’] then
begin
t:= k; Inc(k);
end;
While (k<= length(S)) and (s[k] in ChuSo) do
begin
m:= m*10 + ord(s[k]) - ord(’0’);
Inc(k);
end;
If (t <> 0) and (S[t] = ’-’) then DocSo:= -M
else DocSo:= M;
End;
Procedure Test;
Var St : string;
i : byte;
T : longint;
Begin
St:= ’1’; k:= 1; T:= 0;
For i:= 2 to N do St:= St + D[i] + S[i];
While k < length(St) + 1 do T:= T + DocSo(St);
If T = 0 then
begin
Inc(dem); M[dem]:= St;
end;
End;
Procedure Try(i: byte);
Var j : byte;
Begin
For j:= 1 to 3 do
begin
D[i]:= Dau[j];
If i = N then Test else try(i+1);
end;
End;
BEGIN
Read_inp;
Try(2);
Write_out;
END.
.
Type MangStr = array[1..15] of string;
Const Fi =’ZERO.INP’;
Fo =’ZERO.OUT’;
Dau : array[1..3] of string[1] = (’-’,’+’,’’);
S : array[1..9] of char =(’1’,’2’,’3’,’4’,’5’,’6’,’7’,’8’,’9’);
ChuSo = [’1’..’9’];
Var N,k,dem: byte;
D : array[2..9] of string[1];
F : Text;
St : String;
M : MangStr;
Procedure Write_out;
Var i : byte;
Begin
Assign(F,Fo); Rewrite(F);
Writeln(F,dem);
For i:= 1 to dem do writeln(F,M[i],’ = 0’);
Close(F); Halt;
End;
Procedure Read_inp;
Begin
Assign(F,Fi); Reset(F);
Read(F,N); Close(F);
If N < 3 then write_out;
End;
Function DocSo(S : String): longint;
Var M : longint;
t : byte;
Begin
M:= 0; t:= 0;
If S[k] in [’+’,’-’] then
begin
t:= k; Inc(k);
end;
While (k<= length(S)) and (s[k] in ChuSo) do
begin
m:= m*10 + ord(s[k]) - ord(’0’);
Inc(k);
end;
If (t <> 0) and (S[t] = ’-’) then DocSo:= -M
else DocSo:= M;
End;
Procedure Test;
Var St : string;
i : byte;
T : longint;
Begin
St:= ’1’; k:= 1; T:= 0;
For i:= 2 to N do St:= St + D[i] + S[i];
While k < length(St) + 1 do T:= T + DocSo(St);
If T = 0 then
begin
Inc(dem); M[dem]:= St;
end;
End;
Procedure Try(i: byte);
Var j : byte;
Begin
For j:= 1 to 3 do
begin
D[i]:= Dau[j];
If i = N then Test else try(i+1);
end;
End;
BEGIN
Read_inp;
Try(2);
Write_out;
END.
.