NỘI DUNGPHẦN I: MỘT SỐ THUẬT TOÁN CƠ BẢN Việc sử dụng máy tính điện tử để giải quyết một bài toán nào đó thường được hiểu một cách không đầy đủ.. Thực ra, giải một bài toán trên máy tính
Trang 1MỤC LỤC
NỘI DUNG 2
PHẦN I: MỘT SỐ THUẬT TOÁN CƠ BẢN 2
1 Thuật toán 3
2 Biễu diễn thuật toán 6
Phần II: BÀI TOÁN TÌM KIẾM 8
1 Định nghĩa Bài toán tìm kiếm 8
2 Phân loại 9
3 Đánh giá hiệu quả của thuật toán 9
4 Giải thuật tìm kiếm 9
PHẦN III: BÀI TOÁN ÁP DỤNG 12
1 Phát biểu bài toán 12
2 Nhận định ban đầu 12
3 Ý tưởng 13
TÀI LIỆU THAM KHẢO 15
Trang 2NỘI DUNG
PHẦN I: MỘT SỐ THUẬT TOÁN CƠ BẢN
Việc sử dụng máy tính điện tử để giải quyết một bài toán nào đó thường được hiểu một cách không đầy đủ Nhiều người cho rằng đó chỉ là việc lập trình thuần túy Thực ra, giải một bài toán trên máy tính điện tử là một quá trình phức tạp, bao gồm nhiều giai đoạn phát triển, mà lập trình chỉ là một trong các giai đoạn đó
Ta hãy xét bài toán giải hệ phương trình đại số tuyến tính trên máy tính Đây là một bài tập khá quen thuộc đối với sinh viên các chuyên ngành kỹ thuật Với một đầu vào như vậy, không ít sinh viên cho rằng chỉ còn một việc duy nhất, đó là viết chương trình
Về mặt lý thuyết, toán học đã giải quyết khá đầy đủ: từ phát biểu bài toán, thuật toán và xây dựng các phân tích về nghiệm của hệ phương trình trong các trường hợp khác nhau Nhưng khi viết chương trình trên máy tính để giải bài toán trên sẽ có một số vấn đề phải làm rõ Thậm chí có những vấn đề gặp phải ngay từ khi viết những dòng đầu tiên trong chương trình như kích thước của hệ phương trình chẳng hạn Số ẩn và số phương trình tối
đa là bao nhiêu? Nếu để ý tiếp ta sẽ thấy ngay một số thông tin mà người lập trình phải biết như: Số ẩn và số phương trình có bằng nhau hay không? Trong trường hợp hệ có nhiều nghiệm thì phải viết ra bao nhiêu nghiệm và những nghiệm nào? Dữ liệu về các hệ
số của phương trình được nhập từ tệp hay từ bàn phím? Giá trị các hệ số đó có quá lớn, quá nhỏ không?
Như vậy, rõ ràng là với một bài toán, người lập trình cần có đầy đủ những thông tin về những yêu cầu chi tiết của đầu bài liên quan đến giới hạn của bộ nhớ, giới hạn của màn hình, giới hạn về thời gian và giới hạn về sai số Trong một số trường hợp những thông tin này được xác định ngay trong đầu bài nhưng trong nhiều trường hợp phải qua một quá trình phân tích mới làm rõ được các thông tin này
Trang 3Người lập trình phải giải quyết một vấn đề, một bài toán trên máy tính cần phải thực hiện một bước rất quan trọng, đó là phân tích bài toán Việc phân tích đầu bài nhằm làm rõ một số thông tin:
a) Yêu cầu của bài toán: Bài toán đòi hỏi giải quyết cái gì trên máy tính Nếu giải quyết vấn đề này trên máy tính thì có gặp khó khăn gì về bộ nhớ, về thời gian tín, về cách giải quyết?
b) Dữ liệu đầu vào và dữ liệu đầu ra của bài toán là gì và như thế nào?
c) Với cách giải quyết đã được lựa chọn có sẵn thuật toán hỗ trợ hay không? Trả lời được một số câu hỏi trên người lập trình mới có thể viết được chương trình đáp ứng yêu cầu đề ra trong bài toán
1 Thuật toán
Thuật toán là một bản liệt kê các chỉ dẫn, các quy tắc cần thực hiện theo từng bước xác định nhằm giải quyết một bài toán đã cho trong một khoảng thời gian hữu hạn
Ví dụ 1: Tìm số lớn nhất trong một dãy hữu hạn các số nguyên
Thuật toán:
1) Đặt giá trị cực đại tạm thời bằng số nguyên đầu tiên trong dãy
2) So sánh số nguyên tiếp theo với giá trị cực đại tạm thời, nếu lớn hơn giá trị cực đại tạm thời thì đặt giá trị cực đại tạm thời bằng số nguyên đó
3) Lặp lại bước 2) nếu còn các số nguyên trong dãy
4) Giá trị cực đại tạm thời ở thời điểm này chính là số nguyên lớn nhất trong dãy
Trên đây là những chỉ dẫn cụ thể từng bước được thể hiện bằng ngôn ngữ thông thường Chúng ta sẽ tìm cách thể hiện lại thuật toán giải bài toán trên theo cách thức khác:
- Dữ liệu vào (input): A là mảng chứa n số nguyên
- Dữ liệu ra (output): max, số lớn nhất trong mảng A
Procedure Tim_max (A: mảng có n số nguyên);
a) Đặt max:= A (1);
b) Xét từ i = 2 đến n
Trang 4Nếu max < A (i) thì đặt max:=A(i);
Bảng mô tả thuật toán có các yếu tố:
a) Tính xác định: Các bước của thuật toán phải được xác định một cách chính xác, các chỉ dẫn phải rõ ràng, có thể thực hiện được
b) Tính hữu hạn: Thuật toán phải kết thúc sau một số hữu hạn bước
c) Tính đúng đắn: Thuật toán phải cho kết quả đúng theo yêu cầu của bài toán đặt ra
d) Tính tổng quát: Thuật toán phải áp dụng được cho mọi bài toán cùng loại, với mọi dữ liệu đầu vào như đã được mô tả
Khi mô tả một thuật toán cần đảm bảo các yếu tố sau đây:
- Dữ liệu đầu vào: Một thuật toán phải mô tả rõ các giá trị đầu vào từ một tập hợp các dữ liệu xác định Ví dụ, dãy số nguyên a(1), a(2),…,a(n), với n<∞; hai số nguyên dương a và b
- Dữ liệu đầu ra: Từ một tập các giá trị đầu vào, thuật toán sẽ tạo ra các giá trị đầu ra Các giá trị đầu ra chính là nghiệm của bài toán Ví dụ, số max là phần tử lớn nhát trong a(1), a(2),…,a(n); số d là ước chung lớn nhất của a và b
Ta xét thuật toán tìm số lớn nhất trong một dãy số nguyên nêu ở ví dụ trên:
- Tính xác định: Mỗi bước của thuật toán chỉ gồm các phép gán, mệnh đề kéo theo
- Tính hữu hạn: Thuật toán dừng sau khi tất cả các thành phần của mảng đã được kiểm tra
- Tính đúng đắn: Sau mỗi bước kiểm tra và so sánh ta sẽ tìm được số lớn nhất trong các số đã được kiểm tra Rõ ràng, sau lần kiểm tra cuối cùng thì xác định được số lớn nhất trong toàn bộ các số đã được kiểm tra, có nghĩa là toàn bộ dãy
- Tính tổng quát: Thuật toán cho phép tìm số lớn nhất của dãy số nguyên hữu hạn
n bất kỳ
Dữ liệu đầu vào đầu ra được mô tả rõ ràng:
+ Dữ liệu đầu vào: Mảng chứa n số nguyên
+ Dữ liệu đầu ra: Số nguyên lớn nhất của mảng đầu vào
Trang 5Ví dụ 2: Cho dãy số nguyên A và số nguyên x Hãy xác định xem số nguyên x có trong mảng A hay không Nếu có, hãy chỉ ra vị trí của x trong mảng A
Thuật toán:
- Input: Mảng A gồm n các số nguyên và số nguyên x
- Output: Chỉ số Index của x nếu thấy hoặc -1 nếu không tìm được x
Procedure Timkiem_TT (A: Mảng số nguyên; x: số nguyên):
+ Index:=1;
+ While (Index <=n) and (x# A (Index)) Do Index:=Index + 1;
+ If Index > n Then Index:=-1;
Thuật toán tìm kiếm nêu trên được gọi là thuật toán tìm kiếm tuần tự hay còn gọi
là tìm kiếm tuyến tính
Ví dụ 3: Cho mảng số nguyên A đã được sắp xếp không gian và số nguyên x Hãy xác định xem số nguyên x có trong mảng A hay không Nếu có, hãy chỉ ra vị trí của x trong mảng A
Dữ liệu đầu vào của bài toán này khác với bài toán trước ở chỗ mảng A được sắp xếp không giảm Nhờ thế mà chúng ta có thể lựa chọn thuật toán tìm kiến nhị phân để giải bài toán này
Thuật toán:
- Input: Mảng A gồm n các số nguyên đã được sắp xếp tăng dần và số nguyên x cần tìm trong danh sách
- Output: Chỉ số Index, chỉ số Index bằng chỉ số phần tử bằng x, hoặc bằng 0 nếu không tìm dược x
Prucedure Timkiem_NP(A: mảng số nguyên; x: số nguyên)
+ CS trái :=1; CS phải :=n;
+ Chưa tìm thấy :=True;
+ While (còn khoảng tìm) and (chưa tìm thấy) Do
Index:= Chỉ số ở giữa CS trái và CS phải;
If x =A(i) Then đặt chưa tìm thấy = false
Trang 6Else khoảng tìm sẽ bị co hẹp;
If x< A(Index) Then CS phải = Index -1 Else CS trái = Index + 1;
+ If chưa tìm thấy Then đặt Index :=0;
Trước khi giải một bài toán trên máy tính người lập trình phải phân tích bài toán, hiểu rõ các yêu cầu và ràng buộc của nó sau đó mới xây dựng thuật giải Thuật giải cũng
có thể được lựa chọn trong các thuật toán quen biết, cũng có thể do người lập trình xây dựng thông qua hiểu biết và cảm nhận của mình
2 Biễu diễn thuật toán
Để có thể thảo luận về thuật toán (hay thuật giải) hoặc chuyển thuật toán thành chương trình trên máy tính, người ta phải tìm cách biểu diễn thuật toán Trong các ví dụ được nêu chúng ta đã biểu diễn chính bằng ngôn ngữ gần tự nhiên hoặc ngôn ngữ gần với ngôn ngữ lập trình (tựa ngôn ngữ lập trình hay còn gọi là giả mã) Trong phần này chúng
ta xem xét kỹ hai ngôn ngữ thường được dùng là sơ đồ khối và giả mã
2.1 Sơ đồ khối
Sơ đồ khối là một ngôn ngữ dùng để biểu diễn thuật toán Sơ đồ khối là một công
cụ giúp cho người lập trình có được một cách xem xét sự làm việc của thuật toán khá chi tiết và cu thể Sơ đồ khối được quy ước bao gồm các nút là hình elip, chữ nhật hoặc hình thoi được nối với nhau bởi các đường chỉ hướng chuyển động trong sơ đồ
- Hai loại nút giới hạn Bắt đầu và Kết thúc thường có hình dạng elip;
- Nút chỉ các thao tác, công việc có dạng hình chữ nhật;
Băt đầu
Kết thúc
i = i + 1
Trang 7- Nút chỉ các điều kiện có dạng hình thoi: Trong các đường nối với nút điều kiện này có hai đường đi ra ứng với hai trường hợp điều kiện đúng hoặc điều kiện sai:
- Các đường nối các nút với nhau
Ví dụ, sơ đồ khối sau đây mô tả thuật toán tìm giá trị lớn nhất trong mảng số A có
n phần tử
ĐK False
True
Bắt đầu Nhập n, A[1…n]
max:= A(1) i:=2
i<=n
Max < A(i)
max:= A(i)
i := i + 1
In giá trị max
Kết thúc
S
Đ
S Đ
Trang 82.2 Giả mã
a) Cấu trúc tuần tự: Liệt kê các công việc, các thao tác theo thứ tự Để hỗ trợ cho việc
theo dõi được thuận tiện cũng có thể thêm số thứ tự
b) Cấu trúc rẽ nhánh:
If (điều kiện) Then (công việc);
If (điều kiện) Then (công việc 1) Else (Công việc 2);
c) Cấu trúc lặp:
For (biến):= (giá trị đầu) to (giá trị cuối) do (công việc);
For (biến):= (giá trị đầu) downto (giá trị cuối) do (công việc);
While (điều kiện) do (công việc);
Repeat
- (công việc 1);
- (công việc 2);
-
- (công việc k);
Until (điều kiện);
2.3 Một số thuật toán quy hoạch động
- Bài toán nhân ma trận
- Tìm đường đi ngắn nhất
- Dãy con dài nhất
Phần II: BÀI TOÁN TÌM KIẾM
1 Định nghĩa Bài toán tìm kiếm
Bài toán tìm kiếm là: Tìm kiếm một phương án, đáp án theo yêu cầu đầu vào VD: - Cho một danh sách xác định vị trí xuất hiện của một phần tử trong danh sách
- Tìm kiếm giải pháp lựa chọn để đạt giá trị cực đại trong bài toán cái túi
Bài toán xảy ra trong hai tình huống:
- Dữ liệu xuất hiện được coi là ngẫu nhiên
- Dữ liệu thỏa mãn một số ràng buộc nhất định
Trang 92 Phân loại
-Tìm kiếm tuần tự
- Tìm kiếm nhị phân
- Tìm kiếm dựa trên quy hoạch
3 Đánh giá hiệu quả của thuật toán
Tính hiệu quả của thuật toán thông thường được đo bởi thời gian (thời gian được
sử dụng để tính bằng máy hoặc bằng phương pháp thủ công) – độ phức tạp thời gian, khi các giá trị đầu vào có kích thước xác định Tính hiệu quả của thuật toán cũng được xem xét theo thước đo dung lượng bộ nhớ đã sử dụng để tính toán khi kích thước đầu vào đã xác định – độ phức tạp không gian
Độ phức tạp không gian gắn liền với việc xem xét các cấu trúc dữ liệu đặc biệt được dùng để thể hiện thuật toán
Độ phức tạp thời gian của một thuật toán thường được biểu diễn thông qua số phép toán trong khi thực hiện thuật toán khi các giá trị dữ liệu đầu vào có kích thước xác định
4 Giải thuật tìm kiếm
Bài toán
Giả sử R là mảng gồm n bản ghi, bản ghi thứ k có một khóa X(k), với k=1,2 ,n Hãy tìm bản ghi có khóa bằng (hoặc bé hơn, lớn hơn) giá trị b cho trước
Giá trị b được gọi là khóa tìm kiếm hay đối trị tìm kiếm Bài toán được gọi là giải xong nếu như tìm được bản ghi thứ k nào đó mà X(k) = b hoặc khẳng định được rằng không có bản ghi nào thỏa mãn điều kiện đặt ra, tức là X(k) b với mọi k=1,2, ,n
4.1.Tìm kiếm tuần tự (Sequential Searching)
Ý tưởng
Trang 10Bắt đầu từ bản ghi thứ nhất (k=1), lần lượt so sánh khóa tìm kiếm b với khóa tương ứng của các bản ghi trong mảng, cho tới khi hoặc là tìm được bản ghi thỏa mãn điều kiện hoặc là hết mảng mà không thấy
Thuật toán
Input: Mảng X[1 n], giá trị b
Output: Chỉ số k [1 n] mà tại đó X(k)=b hoặc 0 nếu X(k) b với k [1 n]
Function TKTT (X: mảng; b: Khóa tìm kiếm): Chỉ số;
Begin
k:=1;
While (X(k) b & (k n) do k:=k+1;
If k=n+1 then TKTT:=0 else TKTT:=k;
End;
Đánh giá thuật toán
Trong trường hợp xấu nhất ta cần 2n phép so sánh Tuy nhiên nếu ta thực hiện một cải tiến nhỏ như sau:
Input: Mảng X[1 n+1], giá trị b
Output: Chỉ số k [1 n] mà tại đó X(k)=b hoặc 0 nếu X(k) b với k [1 n]
Function TKTT (X: mảng; b: Khóa tìm kiếm): Chỉ số;
Begin
X(n+1)=b; k:=1;
While X(k) b do k:=k+1;
If k=n+1 then TKTT:=0 else TKTT:=k;
End;
Thì trong trường hợp xấu nhất ta cần n+1 phép so sánh Trong cả hai trường hợp ta
có độ phức tạp của thuật toán là O(n)
4.2 Tìm kiếm nhị phân
Trang 11Ý tưởng
Trên các bản ghi mà khóa đã được sắp xếp tăng dần so sánh khóa tìm kiếm b với khóa của bản ghi ở giữa của đoạn mảng đang xét Chẳng hạn mảng đang xét là X[l r] thì phần tử (bản ghi) ở giữa là X(k) với k=(l+r)/2; nếu X(k)=b thì việc tìm kiếm kết thúc, nếu X(k)<b thì việc tìm kiếm tiếp tục được thực hiện trên mảng con X[l,k-1], trong trường hợp X(k)>b thì việc tìm kiếm sẽ được thực hiện trên mảng con X[k+1,r] Quá trình tìm kiếm trên mảng con sẽ được tiếp tục với thủ tục nêu trên
Thuật toán
Input: Mảng X[1 n], giá trị b
Output: Chỉ số k [1 n] mà tại đó X(k)=b hoặc nếu X(k) b với k [1 n]
Function TKNP (b: Khóa tìm kiếm): Chỉ số;
Begin
TKNP:=0;
can_trai:=1; can_phai:=n;
While can_trai can_phai do
Begin
K:=(can_trai + can+phai)/2;
If X(k) = b then
TKNP:=k;
Exit_loop;
Else If b< X(k) then can_phai:= k-1
Else can_trai:= k+1;
End End;
Đánh giá thuật toán
Trang 12Ta sẽ đánh giá vòng lặp mà thuật toán phải thực hiện Giả sử n=2d Trong trường hợp xấu nhất thuật toán thực hiện tới d vòng lặp Mỗi vòng lặp có thể có tới 3 phép so sánh Như vậy số tối đa phép so sánh mà thuật toán phải thực hiện là 3d hay 3[log2n]+3 với n tùy ý Vậy độ phức tạp của thuật toán là O(log2n)
4.3 Tìm kiếm dựa trên quy hoạch động
Bài toán Dãy con dài nhất
Bài toán:
Cho dãy có n số S={X(1), X(2, ,X(n)} Hãy tìm dãy con đơn điệu tăng (không giảm) S’={X(p1), X(p2), , X(pn)}, với p1< p2< < pk, có nhiều phần tử nhất, có nghĩa là k lớn nhất
Thuật toán:
1 Procedure Gán nhãn
{Kí hiệu L(i) – nhãn của X(i)}
1) L(1):= 1;
2) For i:=2 to n do
If (tồn tại X(j) với j<i) Then
L(i):= max {L(j)+1:X(j)< X(i), j=1,2, , i-1}
Else L(i):= 1;
PHẦN III: BÀI TOÁN ÁP DỤNG
1 Phát biểu bài toán
Cho dãy X gồm n số nguyên n ≤ 1000000 Hãy tìm dãy con đơn điệu gồm các phần tử liên tiếp của X sao cho có nhiều phần tử nhất Ví dụ, nếu X = { 12, 2, 3, 4, 6, 7,
1, 9, 10 } thì dãy con cần tìm là {2, 3, 4, 6, 7} có 5 phần tử
2 Nhận định ban đầu
Trang 13- Số dãy con của x:
Chúng ta có thể xem mỗi dãy con x của X tương đương với một chuỗi nhị phân b,
độ dài n trong đó, b i = 0 nghĩa là a i không thuộc a và ngược lại b i = 1 nghĩa là a i thuộc a.
Ví dụ nếu X = [1, 3, 2, 3] thì dãy con tương ứng với chuỗi nhị phân b = 1010 là [1, 3] Như vậy, số dãy con của X cũng chính là số chuỗi nhị phân có độ dài n chính là 2 n Mặc
dù có thể với 2 chuỗi nhị phân khác nhau sẽ tương ứng với cùng một dãy con (với
mảng X = [1, 3, 2, 3], hai chuỗi 1100 và 1001 cùng tương ứng với dãy con [1, 3]), nhưng
nếu lập trình bình thường để duyệt tất cả các dãy con của X thì phải duyệt 2n phần tử
Với n = 100 thì có đến 2100≈ 1030 dãy con
- Phương án khả thi:
Phương án duyệt tất cả các dãy con để tìm kết quả tối ưu có độ phức tạp là O (2n),
rõ ràng là không khả thi khi n lớn Do đó chúng ta sẽ sử dụng thuật toán quy hoạch động
để giải bài toán
3 Ý tưởng
- Đầu tiên xét for (int i=1; i<m; i++)
- Kiểm tra nếu a[i - 1] < = a [i] thì dãy tăng, ta thực hiện
{
maxT=lt[i-1]+1;
}
lt[i] = maxT;
if(maxT > maxTang)
{
maxTang = maxT;
}
Nếu a[i ] < = a [i - 1] thì dãy giảm, ta thực hiện
{
maxG=lg[i-1]+1;