Professional Documents
Culture Documents
Lecture 03 - BG - 03 - Ky Thuat Cau Truc
Lecture 03 - BG - 03 - Ky Thuat Cau Truc
THUẬT TOÁN 1
Một số kỹ thuật thiết kế
Ý tưởng:
Thực hiện các công việc một cách tuần tự
cho đến khi kết thúc (ra kết quả).
4
1. Kỹ thuật thiết kế tuần tự (2)
Ví dụ 2.1:
Cho số nguyên a có không quá 100 chữ số và
số nguyên b, 1 b 9.
Tính c = ab.
5
1. Kỹ thuật thiết kế tuần tự (3)
6 9 = 54 + 0 = 54
6
1. Kỹ thuật thiết kế tuần tự (4)
Bước 2:
b= 6
a= 6 7 8 9
c= 3 4
nhớ 5 5 0
6 8 = 48 + 5 = 53
7
1. Kỹ thuật thiết kế tuần tự (5)
Bước 3:
b= 6
a= 6 7 8 9
c= 7 3 4
nhớ 4 5 5 0
6 7 = 42 + 5 = 47
8
1. Kỹ thuật thiết kế tuần tự (6)
Bước 4:
b= 6
a= 6 7 8 9
c= 0 7 3 4
nhớ 4 4 5 5 0
6 7 = 42 + 5 = 47
9
1. Kỹ thuật thiết kế tuần tự (7)
Bước 5:
b= 6
a= 6 7 8 9
c= 4 0 7 3 4
nhớ 4 4 5 5 0
4+0=4
Kết quả:
c = 40734
10
1. Kỹ thuật thiết kế tuần tự (8)
Thuật toán:
input: a = (a[n], ...., a[1]) N, n ≤ 100; b {0, 1, ..., 9}
output: c=ab
1) nhớ = 0;
2) Nhân tuần tự từ a[1] đến a[n], mỗi lần cộng với nhớ
cho kết quả tg. Mỗi lần nhân, phần dư (tg mod 10)
đưa vào c, thương tg/10 đưa vào nhớ cho lần sau.
3) Cuối cùng, nếu nhớ > 0 thêm nhớ vào chữ số thứ
n+1 cho c
4) output c = (c[n+1] c[n], ...c[1]);
11
1. Kỹ thuật thiết kế tuần tự (9)
Thuật toán:
input: a = (a[n], ...., a[1]) N, n ≤ 100; b {0, 1, ..., 9}
output: c=ab
1) nhớ = 0;
2) for (i = 1; i ≤ n; i++)
a) tg = b*a[i] + nhớ;
b) c[i] = tg % 10;
c) nhớ = tg/10;
3) if (nhớ > 0)
{n++; c[n] = nhớ;}
4) output c = (c[n]...c[1]);
12
1. Kỹ thuật thiết kế tuần tự (10)
1) nhớ = 0;
2) for (i = 1; i ≤ n; i++)
a) tg = b*a[i] + nhớ;
b) c[i] = tg % 10;
c) nhớ = tg/10;
3) if (nhớ > 0)
{n++; c[n] = nhớ;}
4) output c = (c[n]...c[1]);
13
1. Kỹ thuật thiết kế tuần tự (11)
Ví dụ 2.2:
Cho dãy X có n số nguyên X = {X1, X2, ..., Xn}. Tìm
dãy con A không giảm dài nhất gồm các phần tử liên
tiếp của X.
Ví dụ, dãy X có 8 phần tử
X = { 3, 2, 4, 6, 9, 12, 1, 4 }
thì dãy con liên tiếp không giảm dài nhất là dãy con
A = {2, 4, 6, 9, 12}
gồm các phần tử X2, X3, X4, X5, X6.
14
1. Kỹ thuật thiết kế tuần tự (12)
Ý tưởng:
1. kí hiệu đoạn không giảm dài nhất ban đầu là {Xio,...,Xjo}, io=1, jo = 1.
2. xét từ i =1
3. while (i ≤ n)
a) Tìm đoạn không giảm liên tiếp dài nhất kể từ i, kí hiệu chỉ số
cuối là j, nghĩa là Xj-1 ≤ Xj, Xj > Xj+1
b) Nếu dài hơn đoạn (io, jo) thì lưu lại đoạn mới (io, jo) = (i,j);
c) Đặt lại i = j+1;
4. output cặp chỉ số đầu cuối (io, jo) và đoạn {Xio, ..., Xjo}
15
1. Kỹ thuật thiết kế tuần tự (13)
Chi tiết:
input: X1, X2, ..., Xn; Xi R
output: {io, jo} sao cho Xio ≤ ... ≤ Xjo, jo-io lớn nhất
1) io=1; jo = 1;
2) i = 1;
3) while (i ≤ n)
a) while (Xj ≤ Xj+1) j++;
b) if (j-i > jo – io) {io = i; jo = j;}
c) i = j+1; j = I;
4) output io, jo;
Độ phức tạp của thuật toán là O(n).
16
Một số kỹ thuật thiết kế
Ý tưởng:
Phân chia lời giải bài toán thành các nhiệm vụ có kích thước dữ
liệu nhỏ hơn hoặc có thiết kế đơn giản hơn nhằm
dễ kiểm tra hoặc
sử dụng lại các mô-đun sẵn có.
Nếu các nhiệm vụ đó là mới thì thiết kế các nhiệm vụ đó. Trong
trường hợp các nhiệm vụ này là phức tạp thì có thể phân chia
tiếp.
Còn gọi là kiểu thiết kế top – down: từ ý tưởng đến chi tiết.
18
2. Thiết kế theo cấu trúc (2)
Ví dụ 2.4:
Cho 2 số nguyên a và b có không quá 100 chữ số. Tính c = ab.
19
2. Thiết kế theo cấu trúc (3)
input: a1a2...am và b1b2...bn;
output: c1c2...ck = ab;
1) c = 0;
2) for (i=1; im; i++)
a) tg = nhân_1(ai, b);
b) tg = nhân_2(tg, 10i-1);
c) c = cộng(c, tg);
3) output c;
20
2. Thiết kế theo cấu trúc (4)
input: a1a2...am và b1b2...bn; Thiết kế chi tiết các nhiệm vụ:
output: c1c2...ck = ab; Nhân một số nguyên lớn tg với 10t:
1) c = 0; nhân_2(tg, 10t );
2) for (i=1; im; i++) Chữ số hàng đơn vị lưu trữ ở vị trí 1 của
a) tg = nhân_1(ai, b); mảng, chữ số hàng cao hơn được lưu trữ
b) tg = nhân_2(tg, 10i-1); ở các vị trí cao hơn của mảng.
c) c = cộng(c, tg);
Vì vậy, nhân với 10t thực chất là thêm t chữ số
3) output c; 0 vào phía chỉ số thấp.
Như vậy, phải kéo các chữ số ở hàng cao hơn
về phía sau t vị trí, sau đó thêm t chữ số 0
vào các vị trí từ 1 đến t.
Kí hiệu n là chữ số ở hàng cao nhất của 2 4 5 1 7
tg;
t=3
n = n + t; 2 4 5 1 7
for (i = n; i > t; i--) tg[i] = tg[i-t];
0 0 0 2 4 5 1 7
for (i = 1; i ≤ t; i++) tg[i] = 0;
21
2. Thiết kế theo cấu trúc (5)
input: a1a2...am và b1b2...bn;
output: c1c2...ck = ab;
1) c = 0;
2) for (i=1; im; i++)
a) tg = nhân_1(ai, b); Cộng 2 số nguyên lớn c và tg: cộng(c, tg)
b) tg = nhân_2(tg, 10i-1);
m = length (c);
c) c = cộng(c, tg);
n = lenght(tg);
3) output c; k = max { m, n);
23
2. Thiết kế theo cấu trúc (7)
Bài tập:
1) Cho hàm f(x) liên tục trong khoảng [a, b] và có f(a)f(b)<0. Xây dựng
thuật toán không đệ quy giải phương trình f(x) = 0.
Phân tích:
Hàm f(x) liên tục sẽ lấp đầy giá trị các khỏang
[min f(x), max f(x)] và
[f(a), f(b)].
Nếu
f(a).f(b) <0,
do sự lấp đầy, suy ra
ít nhất một xo (a,b) sao cho f(xo) = 0.
Điều này đảm bảo cho tính đúng đắn của phương pháp chia đôi.
24
2. Thiết kế theo cấu trúc (8)
Ý tưởng:
while ! stop
chia đôi [a,b] thành [a, g] và [g, b]
nếu [a, g] chắc chắn chứa nghiệm, đặt [a,b] = [a, g]
ngược lại, đặt [a,b] = [g, b]
chọn xo [a,b];
output xo;
25
2. Thiết kế theo cấu trúc (9)
26
2. Thiết kế theo cấu trúc (10)
while ! stop
chia đôi [a,b] thành [a, g] và [g, b]
nếu [a, g] chắc chắn chứa nghiệm, đặt [a,b] = [a, g]
ngược lại, đặt [a,b] = [g, b]
chọn xo [a,b];
output xo; input f(x), a, b;
output xo: f(xo) = 0;
27
2. Thiết kế theo cấu trúc (11)
Bài tập:
2) Cho a>0, tính gần đúng giá trị của a với sai số cho trước.
Phân tích:
Phương pháp 1:
Đặt f(x) = x2 – a.
f(xo) = 0 xo2 = a
xo = a
Sử dụng chương trình giải phương trình trong ví dụ trước.
28
2. Thiết kế theo cấu trúc (11)
Cho hàm a>0, tính gần đúng giá trị của a với sai số cho trước.
Phương pháp 2:
Dãy xn+1 = (xn + a/xn) /2 có giới hạn là a.
input a, ;
output a
x = 1;
while !stop
x = (x + a/x) /2;
output x;
29
2. Thiết kế theo cấu trúc (12)
Cho hàm a>0, tính gần đúng giá trị của a với sai số cho
trước.
Dãy xn+1 = (xn + a/xn) /2 có giới hạn là a. input a, ;
output a
x = 1;
while !stop
điều kiện stop: x = (x + a/x) /2;
|xn - a | < output x;
có thể thay bằng điều kiện:
|xn+1 – xn| <
30
2. Thiết kế theo cấu trúc (13)
Cho hàm a>0, tính gần đúng giá trị của a với sai số cho
trước.
Dãy xn+1 = (xn + a/xn) /2 có giới hạn là a.
31
2. Thiết kế theo cấu trúc (14)
Cho hàm a>0, tính gần đúng giá trị của a với sai số cho
trước.
Dãy xn+1 = (xn + a/xn) /2, với xo>0 bất kỳ có giới hạn là a.
Vậy {xn} bị chặn Vậy, {xn} đơn điệu giảm. Suy ra, {xn} có giới
hạn, kí hiệu là b. Cần chứng minh a =32 b2.
2. Thiết kế theo cấu trúc (15)
Cho hàm a>0, tính gần đúng giá trị của a với sai số cho
trước.
Dãy xn+1 = (xn + a/xn) /2, với xo>0 bất kỳ có giới hạn là a.
Tính đúng đắn
Mệnh đề 2: lim xn = a
Chứng minh:
Do a < .... xn < ... < x0,
nghĩa là {xn} đơn điệu giảm. bị chặn. Suy ra {xn} có giới hạn, kí hiệu là b.
Cần chứng minh a = b2.
Lấy giới hạn 2 vế của
xn+1 = (xn + a/xn)/2
được
b = (b + a/b)/2
hay
2b = b + a/ b b = a/b b2 = a
33
2. Thiết kế theo cấu trúc (16)
Ví dụ 3.10.
Đồ thị G = {V, E} có n đỉnh, đánh số từ 1 đến n, được cho bởi danh sách cạnh
edge G[m]
struct edge
{ int d, c;
double ts;
}
Tính số màu và đưa ra phương án tô màu của đồ thị.
Lược đồ 1:
Số màu dự kiến = n;
Xét từng phương án (đề nghị)
a) Nếu là PA đúng, tính số màu;
b) Nếu số màu ít hơn số màu đã có thì lưu số màu và PA;
34
2. Thiết kế theo cấu trúc (17)
Ví dụ 3.10.
Đồ thị G = {V, E} có n đỉnh, đánh số từ 1 đến n, được cho bởi danh sách cạnh
edge G[m]
struct edge
{ int d, c;
double ts;
}
Tính số màu và đưa ra phương án tô màu của đồ thị.
Lược đồ 2:
Sh_màu = 1;
for (d = 1; d ≤ n; d++)
a) m = 1;
b) while (m ≤ sh_màu) & (! hợp_lệ(d, m) m++;
c) Màu (d) = m;
d) if (m > sh_màu) sh_màu ++;
35
2. Thiết kế theo cấu trúc (18)
Xét lược đồ 2:
Sh_màu = 1;
màu[1] = 1;
for (d = 2; d ≤ n; d++)
a) m = 1;
b) while (m ≤ sh_màu) & (! hợp_lệ(d, m) m++;
c) màu [d] = m;
d) if (m > sh_màu) sh_màu ++;
36
2. Thiết kế theo cấu trúc (19)
for (i = 1; i ≤ m; i++) i = 1;
if (d = G[i]->d & màu[G[i]->c] = m) or while màu[G[i]->d]
(d = G[i]->c & màu[G[i]->d] = m) màu[G[i]->c] i++
hợp_lệ = false; hợp_lệ = i>m;
37
2. Thiết kế theo cấu trúc (20)