Tải bản đầy đủ (.doc) (16 trang)

BÀI TẬP NGHIÊN CỨU BẰNG PHƯƠNG PHÁP LÀM MỊN DẦ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 (418.64 KB, 16 trang )

Giải quyết vấn đề bằng phương pháp làm mịn dần

TRƯỜNG ĐẠI HỌC SƯ PHẠM HÀ NỘI
KHOA CÔNG NGHỆ THÔNG TIN
TRUNG TÂM GDTX TỈNH LONG AN

GVHD: ThS. Nguyễn Chí Trung
SVTH:

Phạm Ngọc Trọng
Hà Thị Thùy Vân
Nguyễn Thị Hồng Nhung
Nguyễn Thị Kim Ngân
Nguyễn Ngọc Lan

Lớp: Sư phạm tin học K3
LONG AN_NĂM 2016


Giải quyết vấn đề bằng phương pháp làm mịn dần
1. Khái niệm làm mịn dần
– Làm mịn dần là một chiến lược giải quyết vấn đề theo tiếp cận chia để trị
(devide and conquer):
“Phân tích bài toán/thuật toán thành các bài toán/thuật toán con đơn giản hơn.
Quá trình phân tích đó diễn ra đến khi nhận được các bài toán/thuật toán con sơ
cấp (dễ giải quyết hoặc đã biết cách giải quyết).”
– Có hai cách tiếp cận làm mịn dần: Từ trên xuống (top-down) và từ dưới lên
(bottom-up).
Ví dụ: Input: Tọa độ 4 đỉnh một tứ giác; Output: Diện tích tứ giác
– Làm mịn dần từ trên xuống dưới:
o S(tứ giác) → S(tam giác) → Dodaicanh(A, B)


– Làm mịn dần từ dưới lên:
o Dodaicanh(A, B) → S(tam giác) →S(tứ giác)

 Hình ảnh của “Làm mịn dần từ ngoài vào trong”


Giải quyết vấn đề bằng phương pháp làm mịn dần
2. Các bước dạy học thuật toán theo phương pháp làm mịn dần
 Bước 1. Làm thô: thuật toán chính được phân tích thành các thuật toán
con ở dạng “đóng gói”. Biểu diễn thuật toán chính được thể hiện ở mức
tổng thể, “thô” nhất (kém “mịn” nhất).
 Bước 2. Làm mịn dần: Thực hiện quá trình xây dựng các thuật toán con
theo cách làm như đối với thuật toán chính. Quá trình này thực hiện đến
khi nhận xây dựng được các thuật toán sơ cấp.
 Bước 3. Làm mịn hoàn toàn: Thực hiện quá trình thay thế dần các gói
thuật toán con bằng các biểu diễn chi tiết của chúng đã tìm được ở bước 2.
Khi các thuật toán con được biểu diễn chi tiếp trong thuật toán chính, ta nói
rằng nó được “mở ra”.
Lưu ý: Mỗi bước có thể xchúng em là một giai đoạn nếu như có nhiều bước
nhỏ bên trong

3. Dạy học thuật toán sắp xếp bằng làm mịn dần
• Ví dụ 1: Thuật toán sắp xếp Chọn trực tiếp (selection sort)
 Bước 1: Làm thô


Xét mảng a gồm n phần tử a[1], a[2], …, a[n].




Gọi Q(i) là thuật toán tìm vị trí k của phần tử bé nhất trong dãy từ a[i]
đến a[n].



Và Swap(i, k) là thuật toán hoán đổi giá trị của hai phần tử a[i] và a[k].



Giả sử Q(i) và Swap(i, k) coi như đã biết.

Gọi P là thuật toán sắp xếp tăng dần mảng a. Khi đó P được biểu
diễn như sau:
Phiên bản giả mã: Với mỗi giá trị của i từ 1 đến n-1, thực hiện thuật toán



Q(i, k), nếu k ≠ i thì tiến hành tiếp thuật toán Swap(i, k).
Phiên bản Pascal:
Thuật toán P (dạng thô) for i:=1 to n-1 do
begin
Q(i);
if i <> k then Swap(i, k);
end;


Giải quyết vấn đề bằng phương pháp làm mịn dần
 Bước 2: Làm mịn dần
a) Xét thuật toán Swap(i, k)
Đây là thuật toán hoán đổi giá trị của hai biến mà ta đã biết:

Thuật toán Swap(i, k)
tg := a[i]; a[i] := a[k]; a[k] := tg;
Xét thuật toán Q(i)
Thuật toán này thực chất là thuật toán tìm kiếm tuần tự: Tìm vị trí nhỏ nhất
của một phần tử trong dãy a[i], a[i+1], …, a[n]:
Thuật toán Q(i)
k := i; {Giả sử i là phần tử bé nhất, do đó k = i}
for j:= i + 1 to n do {xét mọi phần tử tiếp theo trong dãy}
if a[j] < a[k] then {nếu gặp phần tử a[j] nào bé hơn a[k]}
k := j; {tiến hành gán lại k bằng vị trí j của phần tử bé hơn đó}
 Bước 3: Làm mịn hoàn toàn
Ghép thuật toán Q(i) và Swap(i,k) vào thuật toán P ta nhận được toàn bộ
thuật toán sắp xếp tăng dần mảng a:
Selection Sort
For i:= 1 to n – 1 do
begin
k := i;
for j:= i + 1 to n do
if a[j] < a[k] then k := j;
if i<> k then
begin
tg := a[i];
a[i] := a[k];
a[k] := tg;
end;
end;


Giải quyết vấn đề bằng phương pháp làm mịn dần
 Ví dụ minh chứng cho thuật toán:


Cho dãy số a={ 12, 2, 8, 5, 1, 6, 4, 15}

+ Khi xét

i=1

Q(1)

Swap(1,5)

1, 2, 8, 5, 12, 6, 4, 15

Swap(2,2)

1, 2, 8, 5, 12, 6, 4, 15

Swap(3,7)

1, 2, 4, 5, 12, 6, 8, 15

Swap(4,4)

1, 2, 4, 5, 12, 6, 8, 15

k=5

+ Khi xét

i=2


Q(2)
k=2

+ Khi xét

i=3

Q(3)
k=7

+ Khi xét

i=4

Q(4)
k=4

+ Khi xét

i=5
k=6


Giải quyết vấn đề bằng phương pháp làm mịn dần
Q(5)
+ Khi xét

Swap(4,6)


1, 2, 4, 5, 6, 12, 8, 15

Swap(6,7)

1, 2, 4, 5, 6, 8, 12, 15

i=6

Q(6)
k=7

Dãy số nhận được sẽ là a={1, 2, 4, 5, 6, 8, 12, 15}
Kết quả chạy chương trình Pascal:

• Ví dụ 2: Thuật toán sắp xếp kiểu nổi bọt (buble sort)
 Bước 1: Làm thô


Xét mảng a gồm n phần tử a[1], a[2], …, a[n].



Gọi Q(i) là thuật toán đưa phần tử nhỏ nhất trong dãy từ a[i-1] đến
a[n] về vị trí i-1 (đầu dãy) theo phương pháp nổi bọt.



Giả sử Q(i) đã biết.

Gọi P là thuật toán sắp xếp tăng dần mảng a. Khi đó P được biểu diễn

như sau:
Phiên bản giả mã:
Thực hiện dãy các thuật toán Q(2), Q(3), …, Q(n).
Phiên bản Pascal:
Thuật toán P (dạng thô) for i:=2 to n do Q(i);


 Bước 2: Làm mịn dần


Giải quyết vấn đề bằng phương pháp làm mịn dần
– Xét thuật toán Q(i)

Thuật toán Q(i)
for j:= n down to i do if a[j] < a[j-1] then Swap(j, j-1).
 Bước 3: Làm mịn hoàn toàn
– Ghép thuật toán Q(i) và Swap(i, k) vào thuật toán P ta nhận được toàn bộ
thuật toán sắp xếp tăng dần mảng a:
– Bubble Sort
for i:= 2 to n do
for j:= n downto i do
if a[j] < a[j-1] then
begin
tg := a[j];
a[j] := a[j-1];
a[j-1] := tg;
end;


Giải quyết vấn đề bằng phương pháp làm mịn dần

 Ví dụ minh chứng cho thuật toán:
Cho dãy số a=(12, 2, 8, 5, 1, 6, 4, 15)


Giải quyết vấn đề bằng phương pháp làm mịn dần

Kết quả chạy chương trình Pascal:

• Ví dụ 3: Thuật toán sắp xếp kiểu chèn trực tiếp (insertion sort)
 Bước 1: Làm thô
– Xét mảng a gồm n phần tử a[1], a[2], …, a[n].
– Gọi Q(x, a, m) là thuật toán chèn phần tử x vào dãy m phần tử a[1], a[2],
… a[m] đã được sắp xếp để nhận được dãy m+1 phần tử a[1], a[2], …
a[m], a[m+1] cũng vẫn được sắp xếp.
– Giả sử Q(x, a, m) đã biết.
– Gọi P là thuật toán sắp xếp tăng dần mảng a. Khi đó P được biểu
diễn như sau:


Giải quyết vấn đề bằng phương pháp làm mịn dần
Phiên bản giả mã:
Thực hiện dãy các thuật toán
Q(a[2], a, 1); Q(a[3], a, 2); Q(a[4], a, 3); … Q(a[n], a, n-1);
Phiên bản Pascal: Thuật toán P (dạng thô)
for i:=2 to n do Q(a[i], a, i-1);
 Bước 2: Làm mịn dần
Thuật toán Q(x, a, m) j := m + 1;
while (a[j-1] < x ) and (j > 1 ) do
begin
a[j] := a[j-1]; j := j – 1;

end;
a[j] := x;
 Bước 3: Làm mịn hoàn toàn
– Ghép thuật toán Q(i, a, k) và Swap(i, k) vào thuật toán P ta nhận được toàn
bộ thuật toán sắp xếp tăng dần mảng a:
– Insertion Sort
for i:= 2 to n do
begin
j := i + 1;
x:= a[i];
while (a[j-1] < x ) and (j > 1 ) do
begin
a[j] := a[j-1];
j := j – 1;
end;
a[j] := x;
end;
 Ví dụ minh chứng cho thuật toán:
Cho dãy số a={ 3, 7, 22, 3, 1, 5, 8, 4, 3, 9}


Giải quyết vấn đề bằng phương pháp làm mịn dần
Kết quả chạy chương trình Pascal:



Ví dụ 4: Thuật toán kiểm tra tính nguyên tố của dãy số nguyên
dương.

 Bước 1: Làm thô

- Xét mảng a gồm n phần tử a[1], a[2], …, a[n].
- Gọi Q(i) là thuật toán tìm vị trí k của phần tử là số nguyên tố trong dãy từ a[i]
đến a[n].
- Giả sử Q(i) coi như đã biết.
- Gọi P là thuật toán tìm kiếm số nguyên tố trong mảng a. Khi đó P được biểu
diễn như sau:
Phiên bản giả mã:
Với mỗi giá trị của i từ 1 đến n, thực hiện thuật toán Q(i).
Phiên bản Pascal:
Thuật toán P (dạng thô) for i:=1 to n do begin Q(i); end;
 Bước 2: Làm mịn dần
Xét thuật toán Q(i)
Thuật toán này thực chất là thuật toán tìm số nguyên tố trong dãy a[i],
a[i+1], …, a[n]:
Thuật toán Q(i)
for i:= 1 to n do {xét mọi phần tử tiếp theo trong dãy}
If (a[i]=0) or (a[i]=1) then {nếu gặp phần tử a[i] nào bằng 0 hoặc 1}
Writeln(a[i],' Khong phai la so nguyen to') {Xuất ra kết quả}
k := 1; {Giả sử ta có k =1}
k := k+1; {tăng k lên 1 giá trị}
Repeat k:= k+1; Until (a[i] mod k= 0) or (k*k>=a[i]);


Giải quyết vấn đề bằng phương pháp làm mịn dần
If k*k>a[i] then Writeln (a[i],' la so nguyen to') { Nếu a[i] không có ước số
trong phạm vi từ 2 đến phần nguyên căn bậc hai của a[i] thì a[i] là số nguyên
tố.
 Bước 3: Làm mịn hoàn toàn
for i:=1 to n do
begin


If (a[i]=0) or (a[i]=1) then
Writeln(a[i],' Khong phai la so nguyen to')
Else Begin

k:=1;
Repeat k:= k+1;
Until (a[i] mod k= 0) or (k*k>=a[i]);
If k*k>a[i] then Writeln (a[i],' la so nguyen to')
else Writeln (a[i],' khong phai la so nguyen to');
end;
end;

 Ví dụ minh chứng thuật toán
Giả sư bạn muốn nhập vào 5 phần tử gồm: a={ 4, 23, 1, 7, 8}. Theo thuật toán ta tính
như sau:

+ Khi i:=1 a[1]:=4 khác 0 và 1 nên ta thực hiện gán:
k

a[1] mod k

k*k>=a[1]

1

4

False


2

0

True

do (4 mod 2= 0) và (2*2>=4) nên a[1]:=4 không phải là số nguyên tố.
+ Tăng i:=2 a[2]:=23 khác 0 và 1 nên ta thực hiện gán:
k

a[2] mod k

1
23
2
1
3
2
4
3
5
3
do (5*5>=23) nên a[2]:=23 là số nguyên tố.

k*k>=a[2]
False
False
False
False
True


Tương tự ta có : 1 và 7 cũng là số nguyên tố và 8 không phải là số nguyên tố;
Kết quả chạy chương trình nhận được như sau:


Giải quyết vấn đề bằng phương pháp làm mịn dần



Ví dụ 5: Thuật toán kiểm tra tính chính phương của dãy số
nguyên dương.

 Bước 1: Làm thô
- Xét mảng a gồm n phần tử a[1], a[2], …, a[n].
- Gọi Q(i) là thuật toán tìm vị trí k của phần tử là số chính phương trong dãy từ
a[i] đến a[n].
- Giả sử Q(i) coi như đã biết.
- Gọi P là thuật toán tìm kiếm số chính phương trong mảng a. Khi đó P được
biểu diễn như sau:
Phiên bản giả mã:
Với mỗi giá trị của i từ 1 đến n, thực hiện thuật toán Q(i).
Phiên bản Pascal:
Thuật toán P (dạng thô) for i:=1 to n do begin Q(i); end;
 Bước 2: Làm mịn dần
Xét thuật toán Q(i)
Thuật toán này thực chất là thuật toán tìm số chính phương trong dãy a[i],
a[i+1], …, a[n]
Thuật toán Q(i)
for i:= 1 to n do {xét mọi phần tử tiếp theo trong dãy}
x:=trunc(sqrt(A[i])); {gán x bằng phần nguyên căn bặc hai của a[i]}

if sqr(x)=a[i] then {Nếu bình phương x bằng a[i] thì a[i] là số chính
phương}
Write(A[i]:4);

{Xuất a[i]: số chính phương}

 Bước 3: Làm mịn hoàn toàn
For i:=1 to n do

Begin
x:=trunc(sqrt(a[i]));


Giải quyết vấn đề bằng phương pháp làm mịn dần
if sqr(x):=a[i] then
Write(a[i]:4);
End;
 Ví dụ minh chứng thuật toán
Giả sư bạn muốn nhập vào 6 phần tử gồm: a={ 1, 7, 9, 16, 3, 2}. Theo thuật toán ta tính
như sau:

+ Khi i:=1 a[1]:=1 ta thực hiện tính:
x:=trunc(sqrt(a[1]))

sqr(x):=a[1]

1

True


do sqr(1)=a[1]nên a[1]:=1 không phải là số chính phương.
Từ đó, ta xác định 1 luôn là số chính phương. Ta có thể gán thêm điều kiện khi a[i]=1;

+ Tăng i:=2 a[2]:=7 ta thực hiện tính:
x:=trunc(sqrt(a[1]))

sqr(x):=a[1]

3

False

do sqr(3)>a[2]nên a[2]:=7 không phải là số chính phương.
+ Tăng i:=3 a[3]:=9 ta thực hiện tính:
x:=trunc(sqrt(a[1]))

sqr(x):=a[1]

3

True

do sqr(3)=a[3]nên a[3]:=9 là số chính phương.
Tương tự ta có : 16 là số chính phương; 3 và 2 không là số chính phương

Kết quả chạy chương trình nhận được như sau:


Giải quyết vấn đề bằng phương pháp làm mịn dần
• Ví dụ 6: Thuật toán tìm ước chung lớn nhất.

 Bước 1: Làm thô
- Xét hai số M, N;
- Gọi Q(i) là thuật toán tính ước số chung của các số trong dãy từ a[i] đến
a[n].
- Và selection_sort: sắp xếp giảm dần.
- Giả sử Q(i) và selection_sort coi như đã biết.
- Gọi P là thuật toán tìm ước chung lớn nhất mảng a. Khi đó P được biểu
diễn như sau:
Phiên bản giả mã:
Với mỗi giá trị của i từ 1 đến n-1, thực hiện thuật toán Q(i, k), nếu k ≠ i
thì tiến hành tiếp thuật toán selection_sort.
Phiên bản Pascal:
While a[1]<>a[n] do
begin
Q(i);
selection_sort;
end;
 Bước 2: Làm mịn dần
Xét thuật toán Q(i)
Thuật toán này là phép gán và thay đổi giá trị cho phần từ thứ a[1].
Thuật toán Q(i):
a[1]:=a[1]-a[n]; { gán a[1] bằng a[1] trừ cho a[n];
 Bước 3: Làm mịn hoàn toàn
While a[1]<>a[n] do
begin
a[1]:=a[1]-a[n];
selection_sort;
end;
UCLN:=a[1];
 Ví dụ minh chứng thuật toán

Tìm ước chung lớn nhất của dãy a:={16, 32, 8, 36}
+ Đầu tiên mảng được sắp xếp lại như sau: a={36, 32, 16, 8}

a[1]-a[4]:=36-8=28 a:={28, 32, 16, 8}sắp xếp lại: a:={32, 28, 16, 8}
+ Tiếp tục
a[1]-a[4]:=32-8=24 a:={24, 28, 16, 8}sắp xếp lại: a:={28, 24, 16, 8}
+ Tiếp tục
a[1]-a[4]:=28-8=20 a:={20, 24, 16, 8}sắp xếp lại: a:={24, 20, 16, 8}


Giải quyết vấn đề bằng phương pháp làm mịn dần
+ Tiếp tục
a[1]-a[4]:=24-8=16 a:={16, 20, 16, 8}sắp xếp lại: a:={20, 16, 16, 8}
+ Tiếp tục
a[1]-a[4]:=20-8=12 a:={12, 16, 16, 8}sắp xếp lại: a:={16, 16, 12, 8}
+ Tiếp tục
a[1]-a[4]:=16-8=8 a:={8, 16, 12, 8}sắp xếp lại: a:={16, 12, 12, 8, 8}
+ Tiếp tục
a[1]-a[4]:=16-8=8 a:={8, 16, 12, 8}sắp xếp lại: a:={16, 16, 12, 8}
.........
Vòng lặp tiếp tục cho đến khi ta nhận được mảng a:={4, 4, 4, 4}
Khi đó ta có Ước chung lớn nhất của dãy đã cho là 4.
 Kết quả chạy chương trình như hình sau:



×