30. Bài Giảng phân tích và thiết kế thuật toán -

57 18 0
30. Bài Giảng phân tích và thiết kế thuật toán -

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Ví duï: trong thuaät toaùn Ôclid sau khi thöïc hieän böôùc 1 chia a cho b ñeå tìm soá dö r ta coù 0<r£b Do ñoù neáu r=0 thì thuaät toaùn döøng sau khi thöïc hieän böôùc 2, coøn r¹ 0[r]

(1)

Bai_tap_Pascal Bai tap Pascal

CÁC THUẬT TOÁN VỀ SỐ

THUẬT TOÁN KIỂM TRA SỐ NGUYÊN TỐ

Thuật toán ta dựa ý tưởng: n >1 không chia hết cho số nguyên tất số từ đến n số nguyên tố Do ta kiểm tra tất số nguyên từ đến có round(sqrt(n)), n khơng chia hết cho số n số nguyên tố

Nếu thấy biểu thức round(sqrt(n)) khó viết ta kiểm tra từ đến n div Hàm kiểm tra nguyên tố nhận vào số nguyên n trả lại kết true (đúng) n nguyên tố trả lại false n không số nguyên tố

function ngto(n:integer):boolean; var i:integer;

begin

ngto:=false; if n<2 then exit;

for i:=2 to trunc(sqrt(n))

if n mod i=0 then exit; {nếu n chia hết cho i n khơng ngun tố => ln} ngto:=true;

end;

Chú ý: Dựa hàm kiểm tra nguyên tố, ta tìm số ngun tố từ đến n cách cho i chạy từ đến n gọi hàm kiểm tra nguyên tố với giá trị i

THUẬT TỐN TÍNH TỔNG CÁC CHỮ SỐ CỦA MỘT SỐ NGUYÊN

Ý tưởng ta chia số cho 10 lấy dư (mod) chữ số hàng đơn vị, lấy số div 10 phần cịn lại Do chia liên tục không chia (số 0), lần chia chữ số ta cộng dồn chữ số vào tổng

(2)

function tongcs(n:integer): integer; var s : integer;

begin

s := 0;

while n <> begin s := s + n mod 10; n := n div 10; end;

tongcs := s; end;

Chú ý: Tính tích chữ số tương tự, cần ý ban đầu gán s thực phép nhân s với n mod 10

THUẬT TỐN EUCLIDE TÍNH UCLN

Ý tưởng thuật toán Euclide UCLN số a,b UCLN số b a mod b, ta đổi a b, b a mod b b Khi UCLN a

Hàm UCLN nhận vào số nguyên a,b trả lại kết UCLN số function UCLN(a,b: integer): integer;

var r : integer; begin

while b<>0 begin r := a mod b; a := b;

b := r; end;

(3)

end;

Chú ý: Dựa thuật tốn tính UCLN ta kiểm tra số nguyên tố hay không Ngồi dùng để tối giản phân số cách chia tử mẫu cho UCLN

THUẬT TỐN TÍNH TỔNG CÁC ƯỚC SỐ CỦA MỘT SỐ NGUYÊN

Để tính tổng ước số số n, ta cho i chạy từ đến n div 2, n chia hết cho số

nào ta cộng số vào tổng (Chú ý cách tính chưa xét n ước số n) function tongus(n : integer): integer;

var i,s : integer; begin

s := 0;

for i := to n div

if n mod i = then s := s + i; tongus := s;

end;

Chú ý: Dựa thuật tốn tính tổng ước số, ta kiểm tra số ngun có số hồn thiện khơng: số ngun gọi số hồn thiện tổng ước số

CÁC THUẬT TỐN VỀ VỊNG LẶP

THUẬT TỐN TÍNH GIAI THỪA MỘT SỐ NGUN

Giai thừa n! tích số từ đến n Vậy hàm giai thừa viết sau: function giaithua(n : integer) : longint;

var i : integer; s : longint; begin

s := 1;

(4)

end;

THUẬT TỐN TÍNH HÀM MŨ

Trong Pascal ta tính ab cơng thức exp(b*ln(a)) Tuy nhiên a số dương khơng thể áp dụng

Ta tính hàm mũ an cơng thức lặp sau: function hammu(a : real; n : integer): real;

var s : real; i : integer; begin

s := 1;

for i := to n s := s * a; hammu := s;

end;

THUẬT TỐN TÍNH CƠNG THỨC CHUỖI

Thuật tốn tính hàm ex:

Đặt: , ta công thức truy hồi:

Khi đó, ta tính cơng thức chuỗi sau: function expn(x: real; n : integer): real;

var s,r : real; i : integer; begin

s := 1; r := 1;

(5)

expn := s; end;

CÁC BÀI TẬP VỀ MẢNG CHIỀU VÀ CHIỀU BÀI TẬP 1

Nhập vào số n (5<=n<=10) n phần tử dãy a, 1<ai<100 (có kiểm tra liệu nhập)

a) In phần tử số nguyên tố dãy

b) Tính ước chung lớn tất phần tử dãy c) Tính biểu thức sau:

d) Sắp xếp dãy tăng dần in dãy sau xếp

HƯỚNG DẪN

Ta nên chia chương trình thành chương trình con, chương trình thực yêu cầu Ngoài ta viết thêm hàm kiểm tra nguyên tố, hàm mũ, hàm UCLN để

thực yêu cầu Chương trình sau: Khai báo liệu: uses crt;

var n : integer;

a : array[1 10] of integer; {n<=10 nên mảng có tối đa 10 phần tử} Thủ tục nhập liệu, có kiểm tra nhập

procedure nhap; var i : integer; begin

clrscr;

(6)

readln(n);

if (5<=n) and (n<=10) then break; {nếu thỗ mãn dừng vịng lặp} writeln('Khong hop le (5<=n<=10) Nhap lai!!!'); {ngược lại báo lỗi} until false;

writeln('NHAP VAO N PHAN TU (1<ai<100)'); for i := to n begin

write('a',i,'='); repeat

readln(a[i]);

if (1<a[i]) and (a[i]<100) then break; writeln('Khong hop le Nhap lai!!!'); until false;

end; end;

function ngto(n : integer): boolean; {hàm kiểm tra nguyên tố, xem giải thích phần trên}

var i : integer; begin

ngto := false; if n < then exit;

for i := to round(sqrt(n)) if n mod i = then exit; ngto := true;

(7)

Thủ tục in số nguyên tố mảng procedure inngto;

var i :integer; begin

writeln('CAC PHAN TU NGUYEN TO TRONG DAY:');

for i := to n {duyệt qua phần tử từ đến n} if ngto(a[i]) then writeln(a[i]); {nếu nguyên tố in ra} end;

function UCLN(a,b: integer): integer; var r : integer;

begin

while b<>0 begin r := a mod b; a := b;

b := r; end;

UCLN := a; end;

Thủ tục tính UCLN phần tử mảng procedure TinhUC;

var i,u : integer; begin

u := a[1]; {u UCLN phần tử từ đến i}

(8)

writeln('UCLN cua ca day la:',u); end;

function hammu(a : real; n : integer): real; {hàm mũ tính an} var s : real; i : integer;

begin

s := 1;

for i := to n s := s * a; hammu := s;

end;

Thủ tục tính tổng phần tử có lấy mũ: procedure tong;

var s : real; i : integer; {s phải khai báo số thực để tránh tràn số} begin

s := 0;

for i := to n s := s + hammu(a[i],i); {s := s + (ai)i} writeln('Tong can tinh:',s:10:0);

end;

Thủ tục xếp tăng dần phần tử mảng: procedure sxep;

var i,j,tg : integer; begin

for i := to n-1

for j := i + to n

(9)

tg := a[i]; a[i] := a[j]; a[j] := tg; end;

writeln('DAY SAU KHI SAP XEP TANG DAN:'); for i := to n writeln(a[i]);

end;

Chương trình chính: gọi thủ tục BEGIN

nhap; inngto; tinhuc; tong; sxep; END

BÀI TẬP 2

Tìm phần tử nhỏ nhất, lớn mảng (cần vị trí phần tử)

HƯỚNG DẪN

Giả sử phần tử cần tìm phần tử k Ban đầu ta cho k=1 Sau cho i chạy từ đến n, a[k] > a[i] rõ ràng a[i] bé hơn, ta gán k i Sau duyệt tồn dãy k số phần tử (Cách tìm đơn giản từ vị trí ta suy giá trị)

procedure timmin; var i, k : integer; begin

k := 1;

for i := to n

(10)

writeln('Phan tu nho nhat la a[',k,']=',a[k]); end;

Tìm max tương tự, thay dấu so sánh procedure timmax;

var i, k : integer; begin

k := 1;

for i := to n

if a[k] < a[i] then k := i;

writeln('Phan tu lon nhat la a[',k,']=',a[k]); end;

Chú ý:

1 Nếu áp dụng với mảng chiều tương tự, khác để duyệt qua phần tử mảng chiều ta phải dùng vịng for Và vị trí phần tử gồm dịng cột

Ví dụ Tìm phần tử nhỏ lớn mảng chiều đổi chỗ chúng cho nhau:

procedure exchange;

var i,j,i1,j1,i2,j2,tg : integer; begin

i1 := 1; j1 := 1; {i1,j1 vị trí phần tử min} i2 := 1; j2 := 1; {i2,j2 vị trí phần tử max} for i := to m

for j := to n begin

(11)

i1 := i; j1 := j; {ghi nhận vị trí mới} end;

if a[i2,j2] < a[i,j] then begin {so sánh tìm max} i2 := i; j2 := j; {ghi nhận vị trí max mới} end;

end;

tg := a[i1,j1]; a[i1,j1] := a[i2,j2]; a[i2,j2] := tg; {đổi chỗ} end;

2 Nếu cần tìm phần tử lớn / nhỏ xếp dòng (1 cột) mảng chiều ta coi dịng (cột) mảng chiều Chẳng hạn tất phần tử dịng k có dạng số a[k,i] với i chạy từ đến n (n số cột)

Ví dụ Tìm phần tử lớn dịng k đổi chỗ phần tử đầu dịng procedure timmax(k : integer);

var i, vt, tg : integer; begin

vt := 1; {vt vị trí phần tử dòng k} for i := to n

if a[k,i] > a[k,vt] then vt := i; {các phần tử dịng k có dạng a[k,i]} tg := a[k,1]; a[k,1] := a[k,vt]; a[k,vt] := tg;

end;

Ví dụ Sắp xếp giảm dần cột thứ k procedure sapxep(k: integer);

var i,j,tg : integer; begin

(12)

for j := i+1 to m

if a[i,k] > a[j,k] then begin {các phần tử cột k có dạng a[i,k]} tg := a[i,k]; a[i,k] := a[j,k]; a[j,k] := tg;

end; end;

BÀI TẬP 3

Tìm phần tử thoả mãn tính chất

HƯỚNG DẪN

Nếu tính chất cần thoả mãn cần kiểm tra phức tạp (chẳng hạn: ngun tố, hồn thiện, có tổng chữ số giá trị cho trước…) ta nên viết hàm để kiểm tra phần tử có tính chất khơng Cịn tính chất cần kiểm tra đơn giản (chẵn / lẻ, dương / âm, chia hết, phương…) khơng cần

Sau ta duyệt qua phần tử từ đầu đến cuối, phần tử thoả mãn tính chất in

Ví dụ In số phương mảng:

Để kiểm tra n có phương khơng, ta lấy n, làm trịn bình phương so sánh với n Nếu biểu thức sqr(round(sqrt(n))) = n true n phương

Vậy để in phần tử phương ta viết: for i := to n begin

if sqr(round(sqrt(a[i]))) = a[i] then writeln(a[i]); Ví dụ In số hoàn thiện từ đến n:

Để kiểm tra số có hồn thiện ta dùng hàm tổng ước (đã có phần đầu) for i := to n begin

if tongus(i) = i then writeln(i);

Ví dụ In phần tử mảng chia dư 1, chia dư 2: for i := to n begin

(13)

Ví dụ In số có chữ số, tổng chữ số 20, chia dư Ta dùng hàm tổng chữ số có trên:

for i := 100 to 999 begin {duyệt qua số có chữ số} if (tongcs(i)=20) and (i mod 7=2) then writeln(i);

Chú ý: Nếu áp dụng với mảng chiều tương tự, khác để duyệt qua phần tử mảng chiều ta phải dùng vịng for

Ví dụ, để in phần tử nguyên tố mảng chiều: for i := to m begin

for j := to n begin

if ngto(a[i,j]) then writeln(a[i,j]);

BÀI TẬP 4

Nhập in mảng chiều dạng ma trận (m dòng, n cột)

HƯỚNG DẪN

Để nhập phần tử mảng chiều dạng ma trận, ta cần dùng lệnh sau unit CRT (nhớ phải có khai báo user crt đầu chương trình)

GotoXY(a,b): di chuyển trỏ hình đến vị trí (a,b) hình (cột a, dịng b) Màn hình có 80 cột 25 dịng

whereX: hàm cho giá trị vị trí cột trỏ hình whereY: hàm cho giá trị vị trí dịng trỏ hình

Khi nhập phần tử ta dùng lệnh readln nên trỏ hình xuống dịng, cần quay lại dịng lệnh GotoXY(j * 10, whereY -1 ), ta muốn phần tử ma trận ứng với 10 cột hình

procedure nhap; var i,j : integer; begin

clrscr;

(14)

for i := to m begin for j := to n begin

write('A[',i,',',j,']='); readln(a[i,j]); {nhập xong xuống dịng} gotoXY(j*10,whereY-1); {di chuyển dịng trước, vị trí tiếp theo} end;

writeln; {nhập xong hàng xuống dịng} end;

end;

Để in bảng dạng ma trận đơn giản hơn, với dòng ta in phần tử hàng xuống dòng:

procedure inbang; var i,j : integer; begin

for i := to m begin {viết phần tử hàng i }

for j := to n write(a[i,j]:6); {mỗi phần tử chiếm ô để phải cho thẳng cột khơng sít nhau}

writeln; {hết hàng xuống dịng} end;

end;

CÁC BÀI TẬP VỀ XÂU KÍ TỰ BÀI TẬP 1

Nhập vào xâu s khác rỗng thực chuẩn hoá xâu, tức là: a) Xoá dấu cách thừa

b) Chuyển kí tự đầu từ thành chữ hoa, kí tự khác thành chữ thường

HƯỚNG DẪN

(15)

var s : string;

procedure chuanhoa(var s : string); {s tham biến để thay đổi chương trình con}

var i : integer; begin

while s[1]=' ' delete(s,1,1); {xoá kí tự cách thừa đầu xâu}

while s[length(s)]=' ' delete(s,length(s),1); {xố kí tự cách thừa cuối xâu} {xố kí tự cách thừa từ: s[i-1] cách s[i] dấu cách thừa Phải dùng vòng lặp for downto q trình xố ta làm giảm chiều dài xâu, for to không dừng được.}

for i := length(s) downto

if (s[i]=' ') and (s[i-1]=' ') then delete(s,i,1); {Chuyển kí tự đầu xâu thành chữ hoa}

s[1] := Upcase(s[1]); for i := to length(s)

if s[i-1]=' ' then s[i] := Upcase(s[i]) {Chuyển s[i] kí tự đầu từ thành chữ hoa.} else

if s[i] in ['A' 'Z'] then {s[i] kí tự chữ hoa khơng đầu từ} s[i] := chr(ord(s[i]) + 32); {thì phải chuyển thành chữ thường} end;

BEGIN

write('Nhap vao xau s:'); readln(s);

chuanhoa(s);

(16)

readln; END

BÀI TẬP 2

Nhập vào xâu x khác rỗng thơng báo xâu có phải xâu đối xứng hay khơng?

HƯỚNG DẪN

Xâu đối xứng xâu đảo Vậy cách đơn giản ta xây dựng xâu đảo x kiểm tra xem có x khơng Để xây dựng xâu đảo x, cách đơn giản cộng kí tự x theo thứ tự ngược (từ cuối đầu)

Chương trình: var x : string;

(************************************************)

function doixung(x : string) : boolean; {hàm kiểm tra xâu đối xứng} var y : string;

i : integer; begin

y := '';

{xây dựng y xâu đảo x, cách cộng dần kí tự x vào y theo thứ tự

ngược}

for i := length(x) downto y := y + x[i]; {so sánh x xâu đảo nó}

if x=y then doixung := true else doixung := false; end;

BEGIN

write('Nhap vao xau:'); readln(x);

(17)

writeln('Xau doi xung!') else

writeln('Xau khong doi xung!'); readln;

END

BÀI TẬP 3

Nhập vào xâu s đếm xem có từ Từ dãy kí tự, cách dấu cách?

HƯỚNG DẪN

Cách đếm từ đơn giản đếm dấu cách: s[i] kí tự khác cách s[i-1] kí tự

cách chứng tỏ s[i] vị trí bắt đầu từ Chú ý từ xâu khơng có dấu cách đứng trước

Chương trình: var s : string;

{Hàm đếm số từ xâu} function sotu(s : string) : integer; var i, dem : integer;

begin

{cộng thêm dấu cách phía trước xâu để đếm từ đầu tiên} s := ' ' + s; dem := 0;

for i := to length(s) {s[i] vị trí bắt đầu từ} if (s[i-1]=' ') and (s[i]<>' ') then dem := dem + 1; sotu := dem;

end; BEGIN

(18)

readln(s);

writeln('So tu xau la:',sotu(s)); readln;

END

BÀI TẬP 4

Nhập vào xâu s in từ (Từ dãy kí tự, cách dấu cách) Xâu có từ đối xứng?

HƯỚNG DẪN

Có nhiều cách để tách xâu thành từ Cách đơn giản tiến hành sau: 1) Bỏ qua dấu cách gặp kí tự khác cách (hoặc hết xâu)

2) Ghi kí tự vào xâu tạm gặp dấu cách hết xâu, ta từ

3) Nếu chưa hết xâu quay lại bước

Mỗi tìm từ, ta ghi ln hình, từ đối xứng tăng biến đếm Ta lưu từ tách vào mảng tập yêu cầu dùng đến từ câu sau

Chương trình: var s : string; dem : integer;

{Hàm kiểm tra từ đối xứng}

function doixung(x : string) : boolean; var y : string;

i : integer; begin

y := '';

(19)

if x=y then doixung := true else doixung := false; end;

{Thủ tục thực tách từ} procedure tach;

var i, len : integer; t : string;

begin

writeln('Cac tu xau:'); i := 1; len := length(s); repeat

{B1: bỏ qua dấu cách hết xâu gặp kí tự khác cách:} while (s[i]=' ') and (i<=len) inc(i);

if i>=len then break; {nếu hết xâu dừng}

t := ''; {t biến tạm lưu từ tách}

{B2: lấy kí tự khác cách đưa vào biến tạm hết xâu gặp kí tự

cách:}

while (s[i]<>' ') and (i<=len) begin t := t + s[i];

inc(i); end;

{in từ vừa tách kiểm tra đối xứng} writeln(t);

(20)

writeln('So tu doi xung xau:',dem); end;

(************************************************) BEGIN

write('Nhap vao xau:'); readln(s);

tach; END

BÀI TẬP 5

Một số nguyên gọi palindrom đọc từ trái sang đọc từ phải sang Ví dụ 121 số palindrom Nhập dãy n phần tử nguyên dương từ bàn phím, 5<= n<=20 phần tử có đến chữ số In số palindrom dãy

HƯỚNG DẪN

Một số palindrom xâu tương ứng xâu đối xứng Ta xây dựng hàm kiểm tra số có phải palindrom khơng cách chuyển số thành xâu kiểm tra xâu có đối xứng khơng?

Chương trình: uses crt;

var n : integer;

a : array[1 20] of integer; {Thủ tục nhập liệu} procedure nhap;

var i : integer; begin

(21)

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

if (n<=20) and (n>=5) then break; {nếu thoả mãn khỏi vịng lặp} writeln('Yeu cau 5<=n<=20 Nhap lai!');

until false; for i := to n repeat

write('A[',i,']='); readln(a[i]);

if (a[i]<=9999) and (a[i]>=10) then break; {a[i] có đến chữ số} writeln('Yeu cau cac phan tu co den chu so Nhap lai!');

until false; end;

{Hàm kiểm tra kiểm tra xâu đối xứng} function palindrom(k : integer): boolean;

var x,y : string; i : integer; begin

str(k,x); {chuyển k thành xâu x} y := '';

for i := length(x) downto y := y + x[i]; {nếu x đối xứng k palindrom}

if x=y then palindrom := true else palindrom := false; end;

(22)

var i : integer; begin

writeln('Cac so la palindrom day:'); for i := to n

if palindrom(a[i]) then writeln(a[i]); readln;

end;

(* Chương trình *) BEGIN

nhap; palin; END

CÁC BÀI TẬP VỀ TỆP BÀI TẬP 1

Nhập mảng chiều m dòng, n cột từ file BANGSO.TXT Cấu trúc file sau: dòng đầu số m n, cách dấu cách, m dòng sau, dòng n số nguyên

a) Hãy in số số nguyên tố mảng b) Tìm vị trí phần tử lớn mảng

c) Sắp xếp dòng mảng tăng dần in mảng dạng ma trận

HƯỚNG DẪN

Ta khai báo mảng chiều nhập liệu từ file vào mảng Quá trình nhập từ file văn giống nhập từ bàn phím, khơng cần thực kiểm tra liệu

Để xếp mảng theo yêu cầu, ta thực xếp dòng mảng cách viết thủ tục xếp (kiểu đổi chỗ cho đơn giản) coi dòng mảng mảng chiều

(23)

a : array[1 100,1 100] of integer; (* Nhập liệu *)

procedure nhap; var f : text; i,j : integer; begin

assign(f,'BANGSO.TXT'); reset(f); readln(f,m,n);

for i := to m

for j := to n read(f,a[i,j]); close(f);

end;

function ngto(k : integer): boolean; var i : integer;

begin

ngto := false; if k < then exit;

for i := to round(sqrt(k)) if k mod i = then exit; ngto := true;

end;

(24)

writeln('Cac phan tu nguyen to cua mang:'); for i := to m

for j := to n

if ngto(a[i,j]) then write(a[i,j],' '); writeln;

end;

procedure timmax;

var max,i,j,im,jm : integer; begin

max := a[1,1]; im := 1; jm := 1; {im, jm lưu toạ độ phần tử đạt max} for i := to m

for j := to n

if max < a[i,j] then begin

max := a[i,j]; {mỗi lần gán max gán toạ độ ln} im := i; jm := j;

end;

writeln('Phan tu lon nhat bang la A[',im,',',jm,']=',max); end;

{Thủ tục thực xếp tăng dần dòng thứ k Các phần từ dịng k có dạng a[k,i]} procedure xepdong(k: integer);

var i,j, tg : integer; begin

(25)

if a[k,i] > a[k,j] then begin

tg := a[k,i]; a[k,i] := a[k,j]; a[k,j] := tg; end;

end;

procedure sapxep; var i,j : integer; begin

for i := to m xepdong(i); {sắp xếp dòng} writeln('Mang sau sap xep:');

for i := to m begin {in dạng ma trận}

for j := to n write(a[i,j] : 5); {in phần tử dòng} writeln; {in hết dịng xuống dịng}

end; end; BEGIN nhap; inngto; timmax; sapxep; END

BÀI TẬP 2

Nhập số m, n từ bàn phím, sau sinh ngẫu nhiên m´n số nguyên ngẫu nhiên có giá trị

từ 15 đến 300 để ghi vào file BANG.TXT Sau thực yêu cầu sau: a) In m´n số sinh dạng ma trận m dòng, n cột

(26)

Yêu cầu: không dùng mảng chiều để lưu trữ liệu

HƯỚNG DẪN

Do yêu cầu không dùng mảng chiều để lưu trữ liệu nên ta đọc file đến đâu, xử lí đến

- Để sinh số ngẫu nhiên từ a đến b, ta dùng biểu thức a + random(b-a+1)

- Để kiểm tra số k có phải số phương khơng, ta lấy bậc k, làm trịn bình phương Nếu kết k k số phương Tức kiểm tra sqr(round(sqrt(k))) = k

Chương trình: var m,n : integer; f : text;

procedure sinh; var

i,j : integer; begin

write('Nhap vao so m,n: '); readln(m,n); assign(f,'BANG.TXT'); rewrite(f);

writeln(f,m,' ',n); for i := to m begin for j := to n

write(f,15 + random(300-15+1) : 6); {sinh số ngẫu nhiên từ 15 đến 300} writeln(f);

end; close(f); end;

(27)

function cp(k : integer) : boolean; begin

if sqr(round(sqrt(k))) = k then cp := true else cp := false;

end;

procedure chinhphuong; var

i,j,k : integer; begin

assign(f,'BANG.TXT'); reset(f); readln(f,m,n);

writeln('CAC SO CHINH PHUONG CUA BANG:'); for i := to m begin

for j := to n begin read(f,k);

if cp(k) then write(k,' '); {vừa đọc vừa xử lí} end;

end; close(f); end;

procedure inbang; var

(28)

assign(f,'BANG.TXT'); reset(f); {mở lại để in dạng ma trận} readln(f,m,n);

writeln(#10,'IN BANG DANG MA TRAN:'); for i := to m begin

for j := to n begin read(f,k);

write(k : 6); {đọc đến đâu in đến đó} end;

writeln; end; close(f); end;

BEGIN sinh;

chinhphuong; inbang;

END

CÁC BÀI TẬP VỀ BẢN GHI BÀI TẬP 1

Viết chương trình quản lí sách Mỗi sách gồm tên sách, tên nhà xuất bản, năm xuất bản, giá tiền, số lượng:

a) Đưa danh sách sách nhà xuất Giáo dục b) Tính tổng số tiền sách

(29)

HƯỚNG DẪN

Mô tả sách ghi, thông tin (tên sách, tên tác giả,…) trường Danh sách sách mảng ghi

Khai báo kiểu liệu mô tả sách sau: type

sach = record

ten : string[30]; {tên sách}

nxb : string[20]; {tên Nhà xuất bản} namxb : integer; {năm xuất bản}

soluong : integer; {số lượng} gia : real; {giá tiền} end;

Thông tin tất sách ta lưu mảng ghi kiểu sach: var

ds : array[1 100] of sach; n : integer;

Nhập liệu: ta nhập tên sách trước Nếu tên sách xâu rỗng đừng nhập, ngược lại nhập thông tin khác:

procedure nhap; var t : string; begin

ClrScr;

(30)

write('Ten sach: '); readln(t);

if t='' then break; n := n + 1;

with ds[n] begin ten := t;

write('NXB: ');readln(nxb);

write('Nam xuat ban: ');readln(namxb); write('So luong: ');readln(soluong); write('Gia tien: ');readln(gia); end;

until false; end;

Câu a: ta duyệt qua toàn danh sách sách, kiểm tra tên nhà xuất Giáo dục in tất thông tin sách tương ứng:

procedure insach; var

i : integer; begin

Clrscr;

writeln('CAC CUON SACH CUA NXB GIAO DUC:'); for i:=1 to n

with ds[i]

(31)

writeln('Ten:',ten);

writeln('Nam xuat ban:',namxb); writeln('So luong:',soluong); writeln('Gia tien:',gia); end;

readln; end;

Câu b: ta duyệt qua toàn sách, nhân số lượng giá tiền cộng dồn vào biến tổng Sau in biến tổng đó:

procedure tinh; var i : integer; tong : real; begin

tong := 0;

for i := to n

with ds[i] tong := tong + gia * soluong;

writeln('TONG GIA TRI CUA TAT CA CAC CUON SACH:', tong:0:3); end;

Câu c: Sắp xếp danh sách giảm dần theo năm xuất phương pháp bọt (2 vòng for) Chú ý biến trung gian đổi chỗ phải có kiểu sach gán

procedure sxep; var i,j : integer; tg : sach; begin

(32)

for j := i + to n

if ds[i].namxb < ds[j].namxb then begin tg := ds[i]; ds[i] := ds[j]; ds[j] := tg; end;

for i:=1 to n with ds[i] begin writeln('Ten:',ten);

writeln('Nam xuat ban:',namxb); writeln('So luong:',soluong); writeln('Gia tien:',gia); end;

readln; end;

Câu d: ta làm tương tự việc in danh sách sách NXB Giáo dục: procedure inds;

var i : integer; begin

writeln('CAC CUON SACH GIA RE HON 10000 VA XUAT BAN TU NAM 2000:'); for i := to n

with ds[i]

if (gia <= 10000) and (namxb >= 2000) then writeln(ten); end;

(33)

nhap; insach; tinh; sxep; inds; readln; END

BÀI TẬP 2

Viết chương trình quản lí cán Thơng tin cán gồm tên, tuổi, hệ số lương, phụ

cấp, thu nhập

a) Nhập thông tin cán từ file văn CANBO.TXT Các thông tin gồm tên, tuổi, hệ

số lương, phụ cấp, thông tin dịng Tính thu nhập = hệ số lương ´ 350000đ + phụ cấp

b) Đưa danh sách trẻ (tuổi <= 30), in đầy đủ thông tin

c) Sắp xếp tên cán theo abc ghi lên file truy cập trực tiếp SAPXEP.DAT

d) Đọc danh sách từ file SAPXEP.DAT, in hình cán có thu nhập từ triệu trở lên

HƯỚNG DẪN

Làm tương tự 1, ý nhập liệu từ file khơng phải từ bàn phím Do không cần ghi thông tin yêu cầu nhập hình Hơn nữa, phải tạo trước file văn CANBO.TXT để chương trình chạy mà khơng báo lỗi

Tồn văn chương trình: uses crt;

type

(34)

hsl, phucap, thunhap: real; end;

var

ds : array[1 100] of canbo; n : integer;

(*********************************************) procedure nhap;

var f : text; begin

assign(f,'CANBO.TXT'); reset(f); n := 0;

while not eof(f) begin n := n + 1;

with ds[n] begin readln(f,ten); readln(f,tuoi); readln(f,hsl); readln(f,phucap);

thunhap := hsl * 350000 + phucap; end;

end; close(f); end;

(35)

procedure in30; var i : integer; begin

writeln('DANH SACH CAC CAN BO TRE:'); for i := to n

with ds[i]

if tuoi <= 30 then begin writeln('Ten:',ten); writeln('Tuoi:',tuoi);

writeln('He so luong:',hsl :0 :3); writeln('Phu cap:',phucap :0 :3); writeln('Thu nhap:',thunhap :0 :3); end;

end;

(*********************************************) procedure sxep;

var i,j : integer; tg : canbo; begin

for i := to n for j := i + to n

(36)

end;

(*********************************************) procedure ghitep;

var f : file of canbo; i : integer;

begin

assign(f,'SAPXEP.DAT'); rewrite(f); for i := to n write(f,ds[i]); close(f);

end;

procedure doctep; var f : file of canbo; i : integer;

begin

assign(f,'SAPXEP.DAT'); reset(f); i := 0;

while not eof(f) begin i := i + 1;

read(f,ds[i]); end;

n := i; close(f); end;

(37)

procedure in3M; var i : integer; begin

writeln('DANH SACH CAC CAN BO CO THU NHAP CAO:'); for i := to n

with ds[i]

if thunhap >= 3000000 then begin writeln('Ten:',ten);

writeln('Tuoi:',tuoi);

writeln('Thu nhap:',thunhap :0 :3); end;

end;

(*********************************************) BEGIN

nhap; in30; sxep; in3M; readln; END

THUẬT TOÁN( GIẢI THUẬT) I)Khái Niệm Thuật Toán:

(38)

IN-PUT) , cho sau số hữu hạn bước thực thao tác ta thu kết quả( OUTPUT) toán

2)Ví dụ: cho hai số nguyên a,b cần xây dựng giải thuật để tìm ước số chung lớn (USCLN) hai số a b Dưới đậy giải thuật nhà toán học cổ Hy Lạp Ơcliđề xuất cho tốn trên:

Giải thuật Ơclid:

- INPUT: a,b nguyeân

- OUTPUT: USCLN a b Bước 1: Chia a cho b tìm số dư r

Bước 2: Nếu r=0 thơng báo kết quả: USCLN b Dừng giải thuật Bước 3: Nếu r ¹ gán trị b cho a , gán trị r cho b quay bước thao tác gồm:

- Phép tìm dư: chia số nnguyên a cho số nguyên b để tìm số dư r - Phép gán trị: đưa giá trị cụ thể vào biến

- Phép chuyển điều khiển: cho phép thực tiếp từ bước ( khơng có gặp phép chuyển tiếp máy thực : sau bước i bước i+1)

Sau phần thể giải thuật Ơclid Ngơn ngữ PASCAL thơng qua chương trình Hàm

{***************************************************} FUNCTION USCLN( a,b:integer) :Integer;

var r :integer; Begin

While b<>0 begin

(39)

b:=r; end;

USCLN:=a; END;

{***************************************} II) Các đặc trưng thuật toán:

1)Thuật tốn phải có tính dừng:

sau số hữu hạn bước phải dừng thuật tốn cho kết

Ví dụ: thuật tốn Ơclid sau thực bước chia a cho b để tìm số dư r ta có 0<r£b Do r=0 thuật tốn dừng sau thực bước 2, cịn r¹ sau bước có phép gán trị b cho a r cho b nên ta thu 0<b<a Điều có nghĩa số dư lần sau nhỏ số dư lần trước Nên sau hữu hạn bước thực r=0 dừng thuật tốn

2)Thuật tốn có tính xác định:

Địi hỏi thuật toán sau bước thao tác phải rõ ràng, không nên gây nhập nhằng , tuỳ tiện nói cách khác điều kiện xử lý nơi cho kết

3)Thuật toán xử lý đại lượng vào(INPUT):

Một giải thuật thường có nhiều đại lượng vào mà ta gọi liệu vào liệu thường biến thiên miền cho trước

4)Thuật toán xử lý đại lượng ra( OUTPUT):

Sau thuật toán thực xong, tuỳ theo chức mà thuật toán đảm nhận ta thu số kết ta gọi đại lượng

5)Thuật toán phải có tính hiệu quả:

tốn có nhiều thuật tốn để giải Trong số thuật toán ta cần chọn thuật toán tốt ,nghĩa thuật tốn phải thực nhanh, tốn nhớ

(40)

thuật toán có khả giải lớp lớn tốn

III)các ví dụ giải thuật số tốn viết

BÀI TỐN 1:

“Viết hàm kiểm tra xem số có phải số ngun tố (số phương, số hồn hảo) hay khơng ? Tìm ước số chung lớn số ?”

Giải thuật cho quen thuộc

* Về số ngun tố : N gọi số nguyên tố N không chia hết số từ Round( sqrt(N))

• Về số phương: N gọi số phương phần thập phân Sqrt(n)

• Về số hồn hảo: N gọi số hồn hảo tổng ước nó( khơng kể nó) ví dụ: N= ,N= 28

{Tồn văn chương trình}

Uses Crt; Var i:Integer;

{***********************************************}

Function Sont(n:Integer):Boolean;{ hàm kiểm tra số nguyên tố} Var i:Integer;

Begin Sont:=False;

For i:=2 to Round(Sqrt(n)) If n Mod i=0 Then Exit;

Sont:=True; End;

(41)

Function Cphuong(n:integer):Boolean;{ kiểm tra số phương} Begin

Cphuong:=sqrt(n)=Round(sqrt(n)); End;

{**********************************************} Function Hoanhao(n:integer):Boolean;

Var s,i:integer; Begin

s:=0;

for i:=1 to n div if n Mod i=0 Then s:=s+i; Hoanhao:=s=n;

End;

{************************************************} Function Uscln(a,b:Integer):Integer;

Var r :Integer; Begin

While b<>0 Do Begin

r:=a Mod b; a:=b;

b:=r;

(42)

End;

{***********************************************} Begin

{Chương trình chính} End

BÀI TỐN 2:

“Tìm số M ,N cho tổng ước dương M bẳng N tổng ước dương N bẳng M với M,N < longint”

ýù tưởng giải thuật:

-Viết hàm tính tổng ước dương số

-Duyệt I=1 n để tóan chạy thời gian chấp nhận ta đặt k= tonguoc(i); Khi

TongUoc(k)=i tỏ ràng I k thỏa mãn đề {Tịan văn chương trình}

{$B-} Uses Crt;

Var k,n,i,j:Longint;

{*****************************************} Function TongUoc(a:Longint):Longint; Var t,s:Longint;

Begin s:=0;

(43)

End;

{*****************************************} BEGIN

Write(‘ nhap N=’); Readln(N);

For i:=1 to N Begin

k:=tonguoc(i);

if TongUoc(k)=i Then Writeln(i,' ',k); End;

END

{******************************} BÀI TỐN 3:

“Phân tích số tự nhiên N thành tích số Ví dụ 90=2*3*3*5”

Ý tưởng giải thuật:

Chia liên tiếp N cho ước nguyên tố bé N, trình dừng lại N=1, lần thực phép chia ta gán lại n := n Div Ntmin(n); Ntmin(n) hàm tìm ước nguyên tố bé N

Hàm tìm ước nguyên tố bé số N dễ hiểu sau: Cho I=2 n i số nguyên tố n chia hết cho i i ước ngun tố bé hàm kiểm tra số có phải số nguyên tố hay không viết hàm NT

(44)

Var N:Integer;

{********************************************} Function NT(n:Integer):Boolean;

Var i:Integer; Begin

Nt:=False;

For i:=2 To N-1 Do

If n Mod i =0 Then Exit; Nt:=True;

End;

{**********************************************} Function NTMIn(n:Integer):Integer;

Var i:Integer; Begin

For i:=2 to N

If nt(i) and (N Mod i=0) Then Begin

ntmin:=i; Exit; End; End;

{**********************************************}

BEGIN

(45)

Readln(n); Until n>1; While n<>1 DO Begin

Write(Ntmin(n):4); n :=n Div Ntmin(n); End;

END BÀI TỐN 4:

Chuyển đổi từ hệ đếm thập phân sang hệ đếm La mã ngược lại ýù tưởng giải thuật:

Chuyển đổi số N từ hệ đếm thập phân sang hệ đếm La Mã:

-Đặt a=n Div 1000 số tương ứng hệ đếm lamã có a ký hiệu M

-Đổi tùng ký số hàng hàng trăm,hàng chục,hàng đơn vị qua số la mã tương ứng với ký số (C,D,M),(X,L,C),(I,V,X)

Ví dụ:4729 Thì a=4

7 trăm phải dùng M,D,C tức số DCC chục phải dùng C,L,X tức số XX đơn vị phải dùng X,V,I tức số IX

Chuyển đổi số S từ hệ đếm hệ đếm La mã sang thập phân:

Giả ta có hàm Doi(ch) để đổi ký số từ hệ la mã sang hệ thập phân Đặt Tam=doi(s[Length(s)])

(46)

- Nếu giá trị ký số <= giá trị ký số liền bên trái kết giá trị cộng với giá trị ký số xét ngược lại trừ giá trị ký số xét

{Tòan văn chương trình} Uses Crt;

{************************************************} Function He10_sang_lama(n:Integer):String; Var s,CH1,CH2,CH3:String;

a,b,K,H,i:Integer; Begin

s:=''; K:=1000; H:=100; a:=n Div k;

For i:=1 to a s:=s+'M'; Repeat

case k of

1000: Begin CH1:='C';CH2:='D';CH3:='M'; End; 100: Begin CH1:='X';CH2:='L';CH3:='C'; End;

10: Begin CH1:='I';CH2:='V';CH3:='X'; End; End;

(47)

3:s:=s+CH1+CH1+CH1; 4:s:=s+CH1+CH2; 5:s:=s+CH2; 6:s:=s+CH2+CH1; 7:s:=s+CH2+CH1+CH1; 8:s:=s+CH2+CH1+CH1+CH1; 9:s:=s+CH1+CH3;

End;

K:=K Div 10; H:=H Div 10; Until k=1;

He10_Sang_lama:=s; End;

{*********************************************} Function lama_sang_he10(s:String):Integer; Var i,tam:Integer;

Function doi(ch:char):Integer;{ haøm doi chương trình ham LaMa_sang_he_10}

Var k:Integer; Begin

Case UPCASE(ch) of 'M':k:=1000;

(48)

'L':k:=50; 'X':k:=10; 'V':k:=5; 'I':k:=1; '0':k:=0;

End; { end of case} DOI:=K;

End;

BEGIN { bắt đầu hàm} Tam:=doi(s[length(s)]);

For i:=length(s)-1 downto if doi(s[i+1])<=doi(s[i]) Then Tam:=Tam+doi(s[i])

Else

Tam:=Tam-doi(s[i]);

LAMA_sang_He10:=Tam; END;{ kết thúc hàm}

{*************************************************} BEGIN { chương trình chính}

Writeln(he10_sang_lama(4729)); END

BÀI TOÁN 5:

(49)

B1 +

B2 +

B3 + B4 +

BK-1 +

BK a)Cho trước S/t tìm dãy bi b)Cho trước dãy bi tìm S/t {Tồn văn chương trình}

Uses Crt;

Var s,t,a,bb,i,k:Integer; b:array[1 12] of Integer;

{*********************************************} Procedure Cau_a;

Begin

Writeln('nhap s,t ');Readln(s,t); i:=0;

(50)

i:=i+1; bb:=t div s; a:=s;

s:=t-bb*s; t:=a;

Write(bb:5); End;

End;

{***************************************************} Procedure Cau_b;

Begin Readln(k); For i:=1 to k Readln(b[i]); s:=1;

t:=b[k];

For i:=k-1 downto Begin

a:=t;

t:=t*b[i]+s; s:=a;

End;

(51)

{************************************************} BEGIN

Cau_a; Cau_b; END

BÀI TỐN 6:

“Hãy tính tổng hai số tự nhiên lớn”

Bài tốn có nhiều cách giải sau nêu lên lời giải tự nhiên hiệu dễ hiểu sau:

Trước hết ta tìm hàm cộng hai chuổi Function Cong(s1,s2:String):String;

Var L1,L2,Max,i,tam,a,b,code,nho:Integer; h,h1:String;

Begin

L1:=length(s1); L2:=length(s2);

if L1>L2 Then Max:=L1 Else Max:=L2; For i:=L1+1 to Max

s1:='0'+s1;

For i:=L2+1 to Max s2:='0'+s2;

nho:=0; h:='';

(52)

Begin

val(s1[i],a,code); val(s2[i],b,code); tam:=a+b+nho;

if tam>=10 Then nho:=1 Else nho:=0;

str(tam Mod 10,h1); h:=h1+h;

End;

if nho=1 Then h:='1'+h; cong:=h;

End;

{******************************************************}

Bây tìm hiểu giải thuật kinh điển cho dạng tốn sau: -Giả sử hai số cho chuổi s1,s2

-Thêm vào bên trái số có chiều dài ngắn để chuổi s1,s2 có chiều dài giả sử chiều dài lúc Max

-Tính c[i]=a[i]+b[i] với i(i=1 Max) Ví dụ: a=986

b=927

Thì c[1]=18; c[2]=10; c[3]=13;

-Để C mảng số kết cần biến đổi chút sau:

Duyệt mảng C từ phải qua trái, c[i] giữ lại phần dư cịn phần ngun cộng thêm cho phần tử c[i-1] sau:

(53)

Begin

c[i-1]:=c[i-1] + c[i] Div 10; c[i]:=c[i] Mod 10;

End;

{Toàn văn chương trình} USES CRT;

Procedure cong; Var s1,s2:String;

a,b,i,L1,L2,code,Max:Word; c:Array[0 100] of Integer; Begin

Readln(s1);Readln(s2); L1:=length(s1);

L2:=length(s2);

if L1>L2 Then Max:=L1 Else Max:=L2; For i:=L2+1 to Max

s2:='0'+s2;

For i:=L1+1 to Max s1:='0'+s1;

Fillchar(C,SizEof(c),0); For i:=1 to Max Begin

(54)

c[i]:=a+b; End;

For i:=Max downto Begin

c[i-1]:=c[i-1] + c[i] Div 10; c[i]:=c[i] Mod 10;

End;

For i:=1 to Max Write(c[i]);

End; BEGIN cong; END

Chương trình trừ số tự nhiên lớn vất vả hơn.theo ý tưởng lấy số có trị tuyệt đối lơn trừ số có trị tuyệt đối nhỏ kết số âm số thứ bé số thứ 2, sau đưa ký tự số lớn vào mảng h1, số bé vào mảng h2.Nếu h1[i]<h2[i]

c[i]:=h1[i]+10-h2[i]; h2[i-1]:=h2[i-1]+1;

ngược lại h1[i]>=h2[i] c[i]:=h1[i]-h2[i];

{Tòan văn chương trình} Procedure tru;

(55)

C:Array[1 100] of Integer; dau:Char;

code,l1,l2,Max,i:word; Begin

Readln(s1);Readln(s2); L1:=length(s1);

L2:=length(s2);

if L1>L2 Then Max:=L1 Else Max:=L2; For i:=L2+1 to Max

s2:='0'+s2;

For i:=L1+1 to Max s1:='0'+s1;

dau:=#32; IF s2>s1 Then Begin

dau:='-'; s:=s2; s2:=s1; s1:=s;

End; Fillchar(C,SizEof(c),0); For i:=1 to Max Begin

(56)

val(s2[i],h2[i],code); End;

For i:=Max downto Begin

IF h1[i]<h2[i] Then Begin

c[i]:=h1[i]+10-h2[i]; h2[i-1]:=h2[i-1]+1; End

Else

c[i]:=h1[i]-h2[i]; End;

Write(dau);

For i:=1 to Max Write(c[i]);

End;

và chương trình nhân số tự nhiên lớn viết sau: {Tồn văn chương trình}

Procedure nhan; Begin

Readln(s1);Readln(s2); L1:=length(s1);

(57)

For i:=1 to L1 For j:=1 to L2 Begin

val(s1[i],A,code); val(s2[J],B,code); c[i+j]:=c[i+j]+a*b; End;

For i:=L1+L2 downto Begin

c[i-1]:=c[i-1] + c[i] Div 10; c[i]:=c[i] Mod 10;

End;

Write('Tich la : '); For i:=2 to L1+L2 Write(c[i]);

End

Ngày đăng: 08/02/2021, 00:35

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan