1. Trang chủ
  2. » Công Nghệ Thông Tin

Bài toán ABBA Xâu đối xứng

7 380 0

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 7
Dung lượng 43 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Chương trình Pascal cho bài toán ABBANguyễn Xuân Huy Trong bài "ABBA hay phép đối xứng gương và các thao tác" đăng trong Tin học & Nhà Trường số 1/1999 có nói đến hai thuật toán giải bài

Trang 1

Chương trình Pascal cho bài toán ABBA

Nguyễn Xuân Huy

Trong bài "ABBA hay phép đối xứng gương và các thao tác" đăng trong Tin học & Nhà Trường số 1/1999 có nói đến hai thuật toán giải bài chuyển các khối bê tông lát đường băng Thể theo yêu cầu của bạn đọc, trong số này chúng tôi sẽ giới thiệu chương trình thực thi và đánh giá độ phức tạp của hai thuật toán đó Chúng tôi cũng sẽ giới thiệu một thủ thuật đơn giản để đo thời gian cho các bạn tiện dùng sau này

Trước hết ta nhắc lại bài toán ở dạng vắn tắt và dễ lập trình như sau:

Bài toán (chuyển phần tử): Cho mảng nguyên a[1 N] và một số tự nhiên K<= N/2 Hãy

chuyển K phần tử từ đầu mảng về cuối mảng

Bài toán này được giải bằng hai giải thuật:

- Giải thuật tự nhiên với độ phức tạp K(N+1) phép gán

- Giải thuật đối xứng với độ phức tạp 3N phép gán

Trước hết ta tổ chức dữ liệu cho bài toán

Tổ chức dữ liệu

Ta dùng một mảng a chứa 16000 phần tử kiểu word Như vậy N sẽ là hằng số có giá trị

16000 Chọn K bằng một nửa của N, tức là chọn 8000 cho giá trị K Các đại lượng này sẽ được khai báo tổng thể như sau:

Const

N=16000;

K=8000;

Type Mang=array[1 N] of word;

Var a: Mang;

Ta sẽ triển khai chương trình cho hai giải thuật như đã giới thiệu trong bài viết ở số 1

Giải thuật tự nhiên

Sơ đồ 1 Sơ đồ thô

Trang 2

Chuyển K lần, mỗi lần 1 phần tử từ đầu mảng về cuối mảng.

Sơ đồ 2 Sơ đồ tinh chế lần thứ nhất

for i :=1 to K do begin

x:= a[1];

{Dịch các phần tử a[2 N] về bên trái một vị trí.}

a[N]:=x;

end;

Để dịch các phần tử a[2 N] về bên trái 1 vị trí ta dùng sơ đồ 3 sau đây:

Sơ đồ 3 Dịch các phần tử a[2 N] về bên trái 1 vị trí

for j:=2 to N do

a[j-1]:=a[j];

Phối hợp các sơ đồ 2 và 3 ta thu được thủ tục ChuyenTuNhien sau đây:

Procedure ChuyenTuNhien;

Var i,j: word;

x: word;

begin

for i:=1 to K do

begin

x:=a[1]; {Lấy phần tử đầu }

{Dịch trái 1 đơn vị}

for j:=2 to N do

a[j-1]:=a[j];

a[N]:=x; {Đặt phần tử đầu vào cuối mảng}

end;

end;

Giải thuật đối xứng

Trước hết xin thay mặt Ban biên tập của phụ san Tin học và Nhà Trường thành thật xin lỗi bạn đọc về một vài lỗi chế bản trong bài đăng ở số 1 Chúng tôi xin đề nghị sửa lại hai lỗi sau:

Lỗi thứ nhất: Trang 12, cột 1, dòng 29 Tính chất 2 của phép đối xứng gương bị in sai,

thay cho dấu nháy kép các bạn sửa giúp lại thành dấu nháy đơn như sau: (AB)' = B'A'

Lỗi thứ hai: Trang 12, cột 1, dòng 49 Xin sửa lại như sau: (A'B')'=B''A''=BA

Trang 3

Sau đây chúng ta triển khai giải thuật đối xứng, thực hiện nhanh hơn giải thuật tự nhiên

Sơ đồ 1 Chuyển đối xứng

Đặt A=a[1 K]; B=a[K+1 N], áp dụng công thức (A'B')'=B''A''=BA ta sẽ thu được ngay kết quả cần tìm Gọi DoiXung(d,c) là thủ thuật thực hiện phép đối xứng đoạn a[d c] của mảng a, nghĩa là Doixung(d,c)=(a[d c])' Ta có ngay giải thuật ChuyenDoiXung sau đây: Procedure ChuyenDoiXung;

Begin

DoiXung(1,K); {A'}

DoiXung(K+1,N); {B'}

DoiXung(1,N); {( )'}

End;

Sơ đồ 2 DoiXung

Thủ tục đối xứng đoạn a[d c] sẽ đổi chỗ từng cặp phần tử cách đều đầu và cuối như sau:

Procedure DoiXung(d,c: word);

Var x: word;

begin

while d

begin

x: =a[d];

a[d]:=a[c];

a[c]:=x;

inc(d);

dec(c);

end;

end;

Kiểm thử chương trình

Để kiểm thử chương trình, chúng ta thực hiện theo sơ đồ sau:

Sơ đồ 1 Kiểm thử một giải thuật

Với mỗi giải thuật ta kiểm thử theo quy trình 5 bước sau:

Bước 1 Sinh ngẫu nhiên dữ liệu cho mảng a.

Bước 2 Ghi nhận thời điểm trước khi thực hiện thủ tục chuyển.

Bước 3 Thực hiện thủ tục chuyển (gọi thuật toán ChuyenTuNhien hoặc thuật toán

ChuyenDoiXung)

Trang 4

Bước 4 Ghi nhận thời điểm sau khi thực hiện thủ tục chuyển.

Bước 5 Thông báo thời gian thực hiện (tức là độ phức tạp tính toán)./p>

Hai cách đo thời gian

Có hai phương thức ghi nhận thời gian trong môi trường Pascal Phương thức thứ nhất là dùng thủ tục Gettime(gio,phut,giay,ptgiay) với các biến kiểu word: gio (giờ), phut (phút), giay (giây) và ptgiay (phần trăm giây) Sau khi lấy được thời điểm trước và thời điểm sau, chúng ta phải tính ra số giây đã chi phí Việc tính toán này được thực hiện trong hệ đếm 60, riêng với phần trăm giây lại phải thực hiện theo hệ đếm thập phân Nếu chỉ cần tính đến giây, ta dùng cách quy đổi ra giây theo mẫu sau:

Sơ đồ 2

Gettime(gio,phut,giay,ptgiay);

Tongsogiaytruoc:=(gio*60+phut)*60+giay;

Thực hiện thủ tục

Gettime(gio,phut,giay,ptgiay);

Tongsogiaysau:=(gio*60+phut)*60+giay;

Tongthoigian:=Tongsogiaysau - Tongsogiaytruoc;

Cách thực hiện trên đòi hỏi nhiều biến và tính toán phiền phức Xin giới thiệu với bạn đọc phương thức truy nhập thời gian một cách trực tiếp Hệ điều hành dành 4 byte trong RAM bắt đầu từ địa chỉ 46c (theo hệ 16) để lưu trữ nhịp làm việc của máy tính Ta có thể truy nhập trực tiếp đến giá trị này bằng cách khai báo một biến mà ta đặt tên là Nhip Biến này phải có độ lớn 4 bytes cho nên ta định kiểu cho nó là longint Biến này phải được cấp phát vào đúng địa chỉ 46c Muốn vậy, bạn phải viết khai báo sau đây:

Nhip: longint absolute $0000:$046c;

Khai báo trên có nghĩa: Cấp phát biến Nhip kiểu longint tại địa chỉ tuyệt đối 46c (hệ 16)

Sử dụng thêm 2 biến t1 và t2 kiểu longint, ta có thể tính được số Nhip cần thiết sau mỗi lần gọi thủ tục nào đó Sơ đồ là như sau:

Sơ đồ 3.

t1: = Nhip;

Thực hiện thủ tục;

t2:=Nhip;

TongsoNhip:=t2-t1;

Tongthoigian:=TongsoNhip/18.2;

Trang 5

Dòng cuối cùng của sơ đồ trên cho ta số giây cần thiết Vì mỗ giây có 18.2 nhịp nên chia

số nhịp cho giá trị này ta thu được số giây Lưu ý bạn đọc rằng biến Tongthoigian phải được khai báo theo kiểu real Còn biến TongsoNhip có thể khai báo là longint

Chương trình

Trong chương trình dưới đây thủ tục Gen sinh N giá trị khởi đầu cho mảng a theo luật, a[i]=i, i=1 N Cấp theo cách đơn giản này sẽ giúp ta dễ theo dõi hoạt động của chương trình

Thủ tục Test1 sẽ thực hiện theo giải thuật tự nhiên, còn thủ tục Test2 dành cho giải thuật đối xứng Với dữ liệu đã cho, Test1 đòi hỏi khoảng 418 nhịp tương ứng với 23 giây, còn Test2 chỉ đòi hỏi 1 nhịp và do đó chỉ tốn 1/18 giây

Thủ tục Doi(s) hiển thị thông báo s trên màn hình và đợi người sử dụng ấn phím để chuyển qua thủ tục khác Thủ tục Xem hiển thị giá trị của mảng a trên màn hình

(*CHUYEN.PAS*)

Uses crt;

Const N=16000;

K=8000;

Type

Mang=array[1 N] of word;

Var Nhip: longint absolute $0000:$046c;

a: Mang;

t1,t2: longint;

Procedure Doi(s: string);

Begin

writeln;

write(s);

repeat until readkey <> #0;

writeln;

End;

Procedure Gen;

Var i: word;

begin

for i:=1 to N do

a[i]:=i;

end;

Procedure Xem;

Var i: word;

begin

Trang 6

for i:=1 to N do

write(a[i]:8);

end;

Procedure ChuyenTuNhien;

Var i,j: word;

x: word;

begin

for i:=1 to K do

begin

x:=a[1]; {Lấy phần tử đầu }

{Tịnh tiến 1 vị trí}

for j:=2 to N do

a[j-1]:=a[j];

a[N]:=x; {Đặt phần tử đầu vào cuối mảng}

end;

end;

Procedure Test1;

Begin

clrscr;

Gen;

Doi('Bam phim tuy y de xem du lieu vao cho giai thuat tu nhien:'); Xem;

Doi(' Bam phim tuy y de thuc hien giai thuat tu nhien:');

writeln('Voi may PC 486 ban phai doi chung 23 ');

t1:=Nhip;

ChuyenTuNhien;

t2:=Nhip;

Doi('Ket thuc giai thuat tu nhien Bam phim tuy y de xem du lieu ra:'); Xem;

Doi('Bam phim tuy y de xem thong bao:');

write('Thoi gian thuc hien giai thuat tu nhien:', t2-t1 , '(nhip)='); writeln(((t2-t1)/18.2):0:0,'(giay)');

Doi('Bam phim tuy y de ket thuc:');

end;

Procedure DoiXung(d,c: word);

Var x: word;

begin

while d

begin

x: =a[d];

a[d]:=a[c];

a[c]:=x;

inc(d);

Trang 7

end;

Procedure ChuyenDoiXung;

Begin

DoiXung(1,K);

DoiXung(K+1,N);

DoiXung(1,N);

End;

Procedure Test2;

begin

clrscr;

Gen;

Doi('Bam phim tuy y de xem du lieu vao cho giai thuat doi xung:'); Xem;

Doi('Bam phim tuy y de thuc hien giai thuat doi xung:');

t1:=Nhip;

ChuyenDoiXung;

t2:=Nhip;

Doi('Ket thuc giai thuat doi xung Bam phim tuy y de xem du lieu ra:'); Xem;

Doi('Bam phim tuy y de xem thong bao:');

write('Thoi gian thuc hien giai thuat doi xung:',t2-t1 , '(nhip)=');

writeln(((t2-t1)/18.2):0:0,'(giay)');

Doi('Bam phim tuy y de ket thuc:');

end;

BEGIN

Test2;

Test1;

END

Ngày đăng: 06/07/2017, 14:09

TỪ KHÓA LIÊN QUAN

w