BÀI TẬP 52: BIỂU THỨC ZERO (Giải Đề thi HSG cấp Tỉnh Thanh Hoá 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 cộng (+)dấu trừ (-) 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ò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.

          Ví dụ:

ZERO.INP

ZERO.OUT

7

6

1-2-3-4-5+6+7 = 0

1-2+3+4-5+6-7 = 0

1-23-45+67 = 0

1-23+4+5+6+7 = 0

1+2-3-4+5+6-7 = 0

1+2-3+4-5-6+7 = 0


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 THAM KHẢO:
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.


Nhãn:

Đăng nhận xét

[blogger]

Biểu mẫu liên hệ

Tên

Email *

Thông báo *

Được tạo bởi Blogger.
Javascript DisablePlease Enable Javascript To See All Widget