Tải bản đầy đủ (.pptx) (67 trang)

Phân tích thiết kế thuật toán

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (454.8 KB, 67 trang )

Chương 2. Thiết kế thuật toán

1. Kỹ thuật đệ quy
2. Kỹ thuật chia để trị
3. Kỹ thuật tham ăn
4. Kỹ thuật quy hoạch động


1. Kỹ thuật đệ quy





Đại cương
Phương pháp thiết kế một thuật toán đệ quy
Xây dựng một số thuật toán đệ quy trên một danh sách liên kết đơn


Đại cương




Chương trình đệ quy là chương trình gọi đến chính nó.
Một chương trình đệ quy thì không thể gọi đến chính nó mãi mãi mà phải có
điểm dừng (trường hợp suy biến).


Phương pháp để thiết kế một thuật toán đệ quy





Tham số hoá bài toán
Phân tích trường hợp chung (biểu diễn bài toán dưới dạng bài toán cùng loại
nhưng khác phạm vi giải quyết)



Xác định trường hợp suy biến


Ví dụ: Sắp xếp mảng a gồm n phần tử



Tham số hoá bài toán:

procedure Sort(dau, cuoi: word);



Phân tích trường hợp chung:

Thủ tục Sort(dau, cuoi) có biểu diễn bởi các lệnh:
Sort(dau+1, cuoi);
if a[dau]>a[dau+1] then
begin swap(a[dau],a[dau+1]);
Sort(dau+1, cuoi);
end;




Xác định trường hợp suy biến: dau = cuoi (không làm gì)


procedure Sort(dau, cuoi: word);
Begin
If dau<>cuoi then
begin

Sort(dau+1, cuoi);
if a[dau]>a[dau+1] then
begin swap(a[dau],a[dau+1]);
Sort(dau+1, cuoi);
end;

end;

End;




Lời gọi từ chương trình chính: Sort(1,n);
2
Độ phức tạp tính toán: O(n )


Ví dụ: Tính a




n

Tham số hoá bài toán:

Function Power(a: real; n: byte):real;



Phân tích trường hợp chung:

n
n-1
a = a.a
hay Power(a,n) = a* Power(a,n-1)




Tr.hợp suy biến: n = 1 ( Power(a,1) = a )
Độ phức tạp tính toán: O(n)


n
Ví dụ: Tính a (một cách tính khác)




Phân tích trường hợp chung:

Nếu n chẵn: Power(a,n) = sqr(Power(a,n div 2))
Nếu n lẻ: Power(a,n) = a*sqr(Power(a,n-1 div 2))




Trường hợp suy biến: n = 1 (Power(a,1) = a)
Độ phức tạp tính toán: O(log2n)


Xây dựng một thuật toán đệ quy trên một danh sách liên kết đơn



Xét khai báo cho trước như sau:
Type

TroNut = ^Nut;
Nut = Record
Info: Integer;
Next: TroNut;
End;

Var F: TroNut; {danh sách F}


Viết chương trình con (hàm/thủ tục)





Xem thử có thể biểu diễn: CTC(F, ...) bởi CTC(F^.next, ...)
Ví dụ: Liệt kê giá trị trường Info của mọi nút thuộc danh sách F
Procedure List(F: TroNut);
Begin If F<>nil then
begin writeln(F^.Info);
List(F^.Next);
end;
End;


Bài tập

1. Sắp xếp một danh sách F
2. Hàm Function LaTangDan(F: TroNut): Boolean
kiểm tra tính tăng dần của danh sách F


Sắp xếp một danh sách F
Procedure Sort(F: TroNut);
Begin
If (F<>nil) and (F^.Next<>nil) then
begin Sort(F^.Next);
If F^.Info>F^.Next^.Info then
begin swap(F^.Info, F^.Next^.Info);
Sort(F^.Next);
end;
end;

End;


Hàm Function LaTangDan(F: TroNut): Boolean
kiểm tra tính tăng dần của danh sách F

Function LaTangDan(F: TroNut): Boolean;
Begin
If (F = nil) or (F^.Next = nil) then LaTangDan:= True
else LaTangDan:= (F^.Info< F^.Next^.Info)
and LaTangDan(F^.Next);
End;


2. Kỹ thuật chia để trị





Phương pháp
Mô hình
Một số bài toán


Phương pháp


Ðể giải một bài toán kích thước n, ta chia bài toán đã cho thành một số bài toán con có kích thưóc nhỏ hơn.
Giải các bài toán con này rồi tổng hợp kết quả lại để được lời giải của bài toán ban đầu.




Ðối với các bài toán con, chúng ta lại sử dụng kĩ thuật chia để trị để có được các bài toán kích thước nhỏ
hơn nữa. Quá trình trên sẽ dẫn đến những bài toán mà lời giải của chúng là hiển nhiên hoặc dễ dàng thực
hiện bài toán cơ sở.


Mô hình
Nếu gọi CDT(R) là hàm thể hiện cách giải bài toán theo phương pháp chia để trị thì
ta có thể viết:
Function CDT(R); {R là kích thước dữ liệu của bài toán}
If (R đủ nhỏ) Then
Giải bài toán
Else
Begin
Chia R thành R1, R2, …, Rm
For i:=1 to m do CDT(Ri);
End;


Một số bài toán
1. Bài toán tìm kiếm nhị phân:
Cho một dãy gồm n phần tử sắp xếp tăng dần và một phần tử X. Tìm X có trong dãy
hay không? Nếu X có trong dãy thì trả về kết quả là True ngược lại là False.




Ý Tưởng: Chia đôi dãy, mỗi lần so sánh phần tử giữa của dãy, nếu phần tử X nhỏ

hơn thì lấy nửa trái, ngược lại lấy nữa phải.



Mô tả thuật toán:
Input: A[1..n]
Output: True or False


Function TKNP(A, X, Dau, Cuoi): Boolean;
If (Dau> Cuoi) then
TKNP:=False
Else
Begin
Giua:=(Dau + Cuoi) div 2;
If (X=A[Giua]) Then TKNP:=True
Else
If (X>A[Giua]) Then TKNP(A, X, Giua +1, Cuoi)
Else
TKNP(A, X, Dau, Giua -1);
End;


2. Bài toán MaxMin




Tìm giá trị Max, Min trong đoạn [l, r] của mảng A[1..n]




Mô tả thuật toán:

Ý tưởng: Tại mỗi bước chia đôi đoạn cần tìm rồi tìm Max, Min trên mỗi đoạn,
sau đó tổng hợp kết quả lại.
Input: A[1..n], l, r (l <=r)
Output: GTMin, GTMax


Function MinMax(A, l, r, GTMin, GTMax)
Begin
If (l=r) Then
Ptử có giá trị Min,Max là A[l]
Else
Begin
MinMax(A, l , (l+r) div 2, GTMin1, GTMax1)
MinMax(A, (l+r) div 2+1, r, GTMin2, GTMax2)
GTMin:=min(GTMin1, GTMin2);
GTMax:=max(GTMax1, GTMax2);
End;


3. Xếp lịch thi đấu thể thao: xét việc xếp lịch thi đấu thể thao theo thể thức đấu
vòng tròn 1 lượt cho n đấu thủ. Mỗi đấu thủ phải đấu với các đấu thủ khác và mỗi
đấu thủ chỉ đấu nhiều nhất một trận mỗi ngày.


••




Tổng số trận đấu của toàn giải là:
 
Nếu n là một số chẵn (n=2k) thì có thể sắp n/2 cặp thi đấu trong một ngày và do
đó cần ít nhất n-1 ngày.
Ngược lại nếu n là một số lẻ thì n-1 là một số chẵn nên ta có thể sắp (n-1)/2 cặp
thi đấu trong một ngày và do đó ta cần n ngày.





Lịch thi đấu là một bảng n dòng và n-1 cột.
Các dòng được đánh số từ 1 đến n và các cột được đánh số từ 1 đến n-1, dòng i biểu diễn
cho đấu thủ i, cột j biểu diễn cho ngày thi đấu j và ô(i,j) ghi đấu thủ phải thi đấu với đấu thủ i
trong ngày j.





Ðể sắp lịch cho n đấu thủ, ta sẽ sắp lịch cho n/2 đấu thủ, để sắp lịch cho n/2 đấu
thủ, ta sẽ sắp lịch cho n/4 đấu thủ...
Bài toán cơ sở là sắp lịch thi đấu cho 2 đấu thủ. Hai đấu thủ này sẽ thi đấu một
trận trong một ngày dễ sắp xếp. Khó khăn: từ các lịch thi đấu cho hai đấu thủ,
ta tổng hợp lại để được lịch thi đấu của 4 đấu thủ, 8 cấu thủ, ...



×