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

Tiểu luận môn thuật toán nâng cao

35 507 2

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 35
Dung lượng 2,6 MB

Nội dung

Thuật toán F giải bài toán P là dãy các thao tác sơ cấp F1, F2,..,FN trên tập dữ kiện đầu vào (Input) để đưa ra được kết quả ra (Output). F1 F2. .FN (Input) Ouput. • F = F1 F2.. FN được gọi là thuật toán giải bài toán P. Trong đó, mỗi Fi chỉ là các phép tính toán số học hoặc logic. • Input được gọi là tập dữ kiện đầu vào (dữ liệu đầu vào). • Output là kết quả nhận được sau khi thực hiện thuật toán F trên tập Input. Một thuật toán cần thỏa mãn các tính chất dưới đây: • Tính đơn định. Ở mỗi bước của thuật toán, các thao tác sơ cấp phải hết sức rõ ràng, không gây nên sự lộn xộn, nhập nhằng, đa nghĩa. Thực hiện đúng các bước của thuật toán trên tập dữ liệu vào, chỉ cho duy nhất một kết quả ra. • Tính dừng. Thuật toán không được rơi vào quá trình vô hạn. Phải dừng lại và cho kết quả sau một số hữu hạn các bước. • Tính đúng. Sau khi thực hiện tất cả các bước của thuật toán theo đúng qui trình đã định, ta phải nhận được kết quả mong muốn với mọi bộ dữ liệu đầu vào. Kết quả đó được kiểm chứng bằng yêu cầu của bài toán. •Tính phổ dụng. Thuật toán phải dễ sửa đổi để thích ứng được với bất kỳ bài toán nào trong lớp các bài toán cùng loại và có thể làm việc trên nhiều loại dữ liệu khác nhau. • Tính khả thi. Thuật toán phải dễ hiểu, dễ cài đặt, thực hiện được trên máy tính với thời gian cho phép. Trong tiểu luận này, tác giả trình bày 8 thuật toán gồm: Đệ quy, vét cạn (duyệt), quy hoạch động, nhánh cận, sinh, quay lui, tham lam, chia và trị. Mỗi thuật toán có 01 ví dụ cụ thể về cách sử dụng thuật toán đó để giải quyết bài toán. Do thời gian có hạn, lượng kiến thức còn hạn hẹp, tác giả rất mong nhận được sự góp ý để tiểu luận được hoàn thiện hơn.

Trang 1

MỤC LỤC

MỞ ĐẦU 3

I PHƯƠNG PHÁP ĐỆ QUY 4

1.1 Khái lược về phương pháp đệ quy 4

1.2 Giải quyết bài toán cụ thể bằng phương pháp đệ quy 4

1.2.1 Phát biểu bài toán 4

1.2.2 Trình bày thuật toán 4

1.2.3 Kiểm nghiệm thuật toán 5

1.2.4 Mã hóa thuật toán 6

1.2.5 Kết quả chạy chương trình 6

II PHƯƠNG PHÁP DUYỆT (VÉT CẠN) 6

2.1 Khái lược về phương pháp vét cạn 6

2.2 Giải quyết bài toán cụ thể bằng phương pháp vét cạn 7

2.2.1 Phát biểu bài toán 7

2.2.2 Trình bày thuật toán 7

2.2.3 Kiểm nghiệm thuật toán 8

2.2.4 Mã hóa thuật toán 8

2.2.5 Kết quả thực hiện chương trình 9

III PHƯƠNG PHÁP QUY HOẠCH ĐỘNG 9

3.1 Khái lược về phương pháp quy hoạch động 9

3.2 Giải quyết bài toán cụ thể bằng phương pháp quy hoạch động 9

3.2.1 Phát biểu bài toán 9

3.2.2 Trình bày thuật toán 10

3.2.3 Kiểm nghiệm thuật toán 12

3.2.4 Mã hóa bài toán bằng phương pháp quy hoạch động 12

3.2.4 Kết quả thực hiên chương trình 13

IV PHƯƠNG PHÁP NHÁNH CẬN 14

4.1 Khái lược về phương pháp nhánh cận 14

4.2 Giải quyết bài toán cụ thể bằng phương pháp nhánh cận 15

4.2.1 Phát biểu bài toán 15

4.2.2 Trình bày thuật toán 15

4.2.3 Kiểm nghiệm thuật toán 17

4.2.4 Mã hóa thuật toán 18

Trang 2

4.2.5 Kết quả thực hiện chương trình 19

V THUẬT TOÁN SINH 19

5.1 Khái lược về thuật toán sinh 19

5.2 Giải quyết bài toán cụ thể bằng thuật toán sinh 19

5.2.1 Phát biểu bài toán 20

5.2.2 Trình bày thuật toán 20

5.2.3 Kiểm nghiệm thuật toán 22

5.2.4 Mã hóa thuật toán 22

5.2.5 Kết quả thực hiện chương trình 23

VI THUẬT TOÁN QUAY LUI 24

6.1 Khái lược về thuật toán quay lui 24

6.2 Giải quyết bài toán cụ thể bằng thuật toán quay lui 24

VII PHƯƠNG PHÁP THAM LAM 26

7.1 Khái lược về phương pháp tham lam 26

7.2 Giải quyết bài toán cụ thể bằng phương pháp tham lam 26

7.2.1 Phát biểu bài toán 26

7.2.2 Trình bày thuật toán 27

7.2.3 Kiểm nghiệm thuật toán 29

7.2.4 Mã hóa thuật toán 29

7.2.5 Kết quả thực hiện chương trình 30

VIII PHƯƠNG PHÁP CHIA VÀ TRỊ 30

8.1 Khái lược về phương pháp chia và trị 30

8.2 Giải quyết bài toán cụ thể bằng phương pháp chia để trị 31

8.2.1 Phát biểu bài toán 31

8.2.2 Trình bày thuật toán 31

8.2.4 Mã hóa thuật toán 33

8.2.5 Kết quả thực hiện chương trình 33

TÀI LIỆU THAM KHẢO 34

Trang 3

MỞ ĐẦU

Thuật toán F giải bài toán P là dãy các thao tác sơ cấp F1, F2, ,FN trêntập dữ kiện đầu vào (Input) để đưa ra được kết quả ra (Output) F1 F2 .FN(Input) Ouput

• F = F1 F2 FN được gọi là thuật toán giải bài toán P Trong đó, mỗi

Fi chỉ là các phép tính toán số học hoặc logic

• Input được gọi là tập dữ kiện đầu vào (dữ liệu đầu vào)

• Output là kết quả nhận được sau khi thực hiện thuật toán F trên tậpInput Một thuật toán cần thỏa mãn các tính chất dưới đây:

• Tính đơn định Ở mỗi bước của thuật toán, các thao tác sơ cấp phải

hết sức rõ ràng, không gây nên sự lộn xộn, nhập nhằng, đa nghĩa Thực hiệnđúng các bước của thuật toán trên tập dữ liệu vào, chỉ cho duy nhất một kếtquả ra

• Tính dừng Thuật toán không được rơi vào quá trình vô hạn Phải

dừng lại và cho kết quả sau một số hữu hạn các bước

• Tính đúng Sau khi thực hiện tất cả các bước của thuật toán theo

đúng qui trình đã định, ta phải nhận được kết quả mong muốn với mọi bộ dữliệu đầu vào Kết quả đó được kiểm chứng bằng yêu cầu của bài toán

•Tính phổ dụng Thuật toán phải dễ sửa đổi để thích ứng được với bất

kỳ bài toán nào trong lớp các bài toán cùng loại và có thể làm việc trên nhiềuloại dữ liệu khác nhau

• Tính khả thi Thuật toán phải dễ hiểu, dễ cài đặt, thực hiện được trên

máy tính với thời gian cho phép

Trong tiểu luận này, tác giả trình bày 8 thuật toán gồm: Đệ quy, vét cạn(duyệt), quy hoạch động, nhánh cận, sinh, quay lui, tham lam, chia và trị Mỗithuật toán có 01 ví dụ cụ thể về cách sử dụng thuật toán đó để giải quyết bàitoán

Do thời gian có hạn, lượng kiến thức còn hạn hẹp, tác giả rất mongnhận được sự góp ý để tiểu luận được hoàn thiện hơn

Trang 4

I PHƯƠNG PHÁP ĐỆ QUY

1.1 Khái lược về phương pháp đệ quy

Phương pháp định nghĩa bằng đệ qui: Một đối tượng được định

nghĩa trực tiếp hoặc gián tiếp thông qua chính nó được gọi là phép định nghĩabằng đệ qui

Thuật toán đệ qui: Thuật toán giải bài toán P trực tiếp hoặc gián tiếp

thông qua bài toán P’ giống như P được gọi là thuật toán đệ qui Một hàmđược gọi là đệ qui nếu nó được gọi trực tiếp hoặc gián tiếp đến chính nó Mộtbài toán giải được bằng đệ qui nếu nó thỏa mãn hai điều kiện:

• Phân tích được: Có thể giải được bài toán P bằng bài toán P’ giống

như P và chỉ khác P ở dữ liệu đầu vào Việc giải bài toán P’ cũng được thực hiện theo cách phân tích giống như P.

• Điều kiện dừng: Dãy các bài toán P’ giống như P là hữu hạn và sẽ

dừng tại một bài toán xác định nào đó.

Thuật toán đệ qui tổng quát có thể được mô tả như sau:

Thuật toán Recursion ( P ) {

1 Nếu P thỏa mãn điều kiện dừng:

<Giải P với điều kiện dừng>;

2 Nếu P không thỏa mãn điều kiện dừng:

Recursion(P’).

}

1.2 Giải quyết bài toán cụ thể bằng phương pháp đệ quy

1.2.1 Phát biểu bài toán

Cho 2 số nguyên dương a và b, viết chương trình tìm ƯCLN (a,b)

1.2.2 Trình bày thuật toán

Ước số chung lớn nhất (ƯCLN) của 2 số nguyên dương a, b là 1 số klớn nhất sao cho a và b đều chia hết cho k Một phương pháp đơn giản nhất

để tìm ƯCLN của a và b là duyệt từ số nhỏ hơn trong 2 số a, b cho đến 1,

Trang 5

ngay khi gặp số nào đó mà a và b đều chia hết cho nó thì đó chính là ƯCLNcủa a, b Tuy nhiên, phương pháp này không phải là cách tìm ƯCLN hiệuquả Cách đây hơn 2000 năm, Euclid đã phát minh ra một giải thuật tìmƯCLN của 2 số nguyên dương a, b rất hiệu quả Ý tưởng cơ bản của thuậttoán này cũng tương tự như ý tưởng đệ qui, tức là đưa bài toán về 1 bài toánđơn giản hơn Cụ thể, giả sử a lớn hơn b, khi đó việc tính ƯCLN của a và b

sẽ được đưa về bài toán tính ƯCLN của a mod b và b vì ƯCLN(a,b) =ƯCLN(a mod b, b)

1.2.3 Kiểm nghiệm thuật toán

Kiểm nghiệm thuật toán để tính ƯCLN của 108 và 45, ta gọi thủ tụcƯCLN(108, 45) Khi đó, các thủ tục sau sẽ lần lượt được gọi:

ƯCLN(108, 45) 108 chia 45 dư 18, do đó tiếp theo gọi

ƯCLN(45, 18) 45 chia 18 dư 9, do đó tiếp theo gọi

ƯCLN(18, 9) 18 chia 9 dư 0, do đó tiếp theo gọi

ƯCLN(9, 0) tham số thứ 2 = 0, do đó kết quả là tham số thứ nhất, tức là 9.

Trang 6

Như vậy, ta tìm được ƯCLN của 108 và 45 là 9 chỉ sau 4 lần gọi thủ tục.

1.2.4 Mã hóa thuật toán

printf ( "Nhap a: " ); scanf ( "%d" ,& a );

printf ( "Nhap b: " ); scanf ( "%d" ,& b );

printf ( "USCLN(%d,%d)=%3d" , a , b , USCLN ( a , b ));

getch ();

}

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

II PHƯƠNG PHÁP DUYỆT (VÉT CẠN)

2.1 Khái lược về phương pháp vét cạn

Vét cạn là phương pháp tìm nghiệm của bài toán bằng cách xem xét tất

cả các phương án có thể xảy ra của bài toán Trong đó:

Trang 7

• Nhược điểm: chỉ thực hiện được trên lớp các bài toán đã có thuật giải.Lớp bài toán này rất nhỏ so với lớp các bài toán thực tế.

Sử dụng máy tính và các công cụ tính toán:

• Giải được mọi bài toán đã có thuật giải bằng máy tính

• Đối với một số bài toán chưa có thuật giải, ta có thể sử dụng máy tính

để xem xét tất cả các khả năng có thể để từ đó đưa ra nghiệm của bài toán

Một thuật toán duyệt cần thỏa mãn hai điều kiện:

• Không được lặp lại bất kỳ khả năng nào.

• Không được bỏ sót bất kỳ cấu hình nào.

2.2 Giải quyết bài toán cụ thể bằng phương pháp vét cạn

2.2.1 Phát biểu bài toán

Trình bày thuật toán và viết chương trình kiểm tra một số nguyên dương a cóphải là số nguyên tố hay không?

2.2.2 Trình bày thuật toán

Số nguyên tố là các số nguyên dương chỉ chia hết cho 1 và chính nó Vậy đểkiểm tra 1 số a có phải là số nguyên tố hay không chúng ta kiểm tra xem a cóchia hết cho số nào khác ngoài 1 và a hay không Nếu tồn tại ít nhất một phépchia hết cho số khác 1 và a thì a không phải là số nguyên tố

Ta sử dụng phương pháp duyệt (vét cạn) để giải quyết bài toán Vậychiến thuật vét cạn cho bài toán này là gì?

Nếu a ==1 hoặc a==2 thì a là số nguyên tố; trong trường hợp a>2chúng ta thực hiện phương pháp lấy a chia cho các số từ 2 đến a – 1, nếu tồntại một giá trị mà a chia hết trong khoảng từ 2 đến a -1 thì a không phải là sốnguyên tố Với cách này thì vòng for sẽ phải chạy từ 2 đến a -1;

Suy nghĩ thêm một chút chúng ta thấy không cần thiết phải kiểm tra a

có chia hết cho tất cả các số từ 2 đến a – 1 mà chỉ cần kiểm tra xem a có chiahết số nào trong khoảng từ 2 đến a/2 thôi Vì a chia cho 1 số lớn hơn a/2 đến a-1 thì kết quả nhận được luôn lớn hơn 1 và nhỏ hơn 2 Do đó a không chia hếtcho các số lớn hơn a/2 Vì vậy chúng ta không cần phải xét các trường hợp

Trang 8

thuộc khoảng từ a/2 đến a-1 Số phép toán duyệt sẽ ít hơn so với phương pháptrên.

Tuy nhiên phương pháp này vẫn chưa tối ưu vì a chỉ có thể chia hết cho

số lớn nhất bằng (trong trường hợp là số nguyên) Do vậy ta chỉ cần xétxem a có chia hết cho các số thuộc khoảng từ 2 đến thôi Số phép toánphải thực hiện sẽ được giảm thiểu hơn so với phương pháp duyệt xem a cóchia hết cho các số từ 2 đến a/2 Do vậy thuật toán để kiểm tra a có phải là sốnguyên tố không như sau:

}

}

Trang 9

int main ( void ){

int a ;

printf ( "Nhap a: " ); scanf ( "%d" ,& a );

if ( KTNT ( a )) printf ( "%d là so nguyen to" , a );

else printf ( "%d khong la so nguyen to" , a );

getch ();

}

2.2.5 Kết quả thực hiện chương trình

III PHƯƠNG PHÁP QUY HOẠCH ĐỘNG

3.1 Khái lược về phương pháp quy hoạch động

Phương pháp qui hoạch động dùng để giải lớp các bài toán thỏa mãnnhững điều kiện sau:

• Bài toán lớn cần giải có thể phân rã được thành nhiều bài toán con.Trong đó, sự phối hợp lời giải của các bài toán con cho ta lời giải của bài toánlớn Bài toán con có lời giải đơn giản được gọi là cơ sở của qui hoạch động.Công thức phối hợp nghiệm của các bài toán con để có nghiệm của bài toánlớn được gọi là công thức truy hồi của qui hoạch động

• Phải có đủ không gian vật lý lưu trữ lời giải các bài toán con (Bảngphương án của qui hoạch động) Vì qui hoạch động đi giải quyết tất cả các bàitoán con, do vậy nếu ta không lưu trữ được lời giải các bài toán con thì khôngthể phối hợp được lời giải giữa các bài toán con

• Quá trình giải quyết từ bài toán cơ sở (bài toán con) để tìm ra lời giảibài toán lớn phải được thực hiện sau hữu hạn bước dựa trên bảng phương áncủa qui hoạch động

3.2 Giải quyết bài toán cụ thể bằng phương pháp quy hoạch động

3.2.1 Phát biểu bài toán

Trong siêu thị có n gói hàng ( n<= 100), gói hàng thứ i có trọng lượng

là W[i] <= 100 và trị giá V[i] <=100 Một tên trộm đột nhập vào siêu thị, tên

Trang 10

trộm mang theo một cái túi có thể mang được tối đa trọng lượng M (M<=100) Hỏi tên trộm sẽ lấy đi những gói hàng nào để được tổng giá trị lớn nhất.

Input:File văn bản BAICAITUI.txt

+ Dòng 1: Chứa 2 số n, M cách nhau ít nhất một dấu cách

+ n dòng tiếp theo: dòng i chứa 2 số nguyên dương W[i], V[i] cáchnhau ít nhất một dấu cách

Output: Tệp văn bản KETQUA.OUT

+Dòng 1: Ghi giá trị lớn nhất tên trộm có thể lấy

+Dòng 2: Ghi chỉ số những gói bị lấy

3.2.2 Trình bày thuật toán

Nếu gọi F[i,j] là giá trị lớn nhất có thể có bằng cách chọn trong các gói{1,2,….,i} với giới hạn trọng lượng j Thì giá trị lớn nhất khi chọn được trong

số n gói giới hạn trọng lượng M chính là F[n,M]

Công thức truy hồi tính F[i,j].

Với giới hạn trọng lượng j, việc chọn tối ưu trong các gói {1 ,2, , i-1,i} để có giá trị lớn nhất sẽ có 2 khả năng:

+ Nếu không chọn gói thứ i thì F[i, j] là giá trị lớn nhất có thể có bằngcách chọn trong số các gói { 1,2,…, i -1 } với giới hạn trọng lượng j Tứclà:F[i,j] = F[i-1,j];

+ Nếu có chọn gói thứ i (tất nhiên chỉ xét trong trường hợp này khi màW[i]<= j) thì F[i,j] bằng giá trị gói thứ i là V[i] cộng với giá trị lớn nhất có thể

có bằng cách chọn trong số các gói {1,2,…, i -1} với giới hạn trọng lượng j –W[i] Tức là về mặt giá trị thu được: F[i,j] = V[i] + F[i-1, j – W[i]];

Trang 11

Vì theo cách xây dựng F[i,j] là giá trị lớn nhất có thể có, nên F[i,j] sẽ làmax trong 2 giá trị thu được ở trên.

Cơ sở quy hoạch động:

Dễ thấy F[0,j] = giá trị lớn nhất có thể có bằng cách chọn 0 gói = 0

// Giai thuat quy hoach dong cho bai toan cai tui

Optimize; //Phương án công thức truy hồi

Trang 12

Write(fo,n,' ');

M:=M-W[n];//chọn gói thứ n rồi thì chỉ có thể mang M-W[n]

Trang 13

int X [ MAX ], Y [ MAX ];//X[i],Y[i]de luu khoi luong va gia tri cua vat thu i

int F [ MAX ][ MAX ];

//F[i][j] la tong gia tri lon nhat ma tui chua duoc neu lay tu 1-i vat

// voi khoi luong gioi han la j

fprintf ( fp , "%5d" , n );// Co the chon duoc vat thu n

m = m - X [ n ]; // Da chon vat thu n thi chi con mang duoc Y[n] khoi luong

Trang 14

IV PHƯƠNG PHÁP NHÁNH CẬN

4.1 Khái lược về phương pháp nhánh cận

Phương pháp (hay giải thuật) nhánh cận là một trong những phương pháp giải các bài toán liệt kê cấu hình có điều kiện tối ưu.

Bài toán tối ưu

- Bài toán yêu cầu tìm ra một phương án tốt nhất thỏa mãn một số yêucầu ràng buộc nào đó – nghiệm của bài toán đạt giá trị max/min trong khônggian nghiệm

- Thuộc lĩnh vực Tối ưu toán học hoặc Quy hoạch toán học Lời giảitoán có thể khó => Sự vào cuộc của Tin học

- Hai hướng tiếp cận tìm lời giải tối ưu cho bài toán:

+ Tìm từng lời giải, khi hoàn tất một lời giải thì so sánh của nó với chiphí tốt nhất hiện có Nếu tốt hơn thì cập nhật chi phí tốt nhất mới

+ Với mỗi lời giải, khi xây dựng các thành phần nghiệm luôn kiểm trađiều kiện nếu đi tiếp theo hướng này thì có khả năng nhận được lời giải tốthơn lời giải hiện có không? Nếu không thì không đi theo hướng này nữa

Bản chất:

+ Sử dụng phương pháp quay lui nhưng tại mỗi bước đưa thêm thao tácđánh giá giá trị phương án hiện có

+ Nếu đó là phương án tối ưu hoặc có hy vọng trở thành phương án tối

ưu (tức là tốt hơn phương án hiện có) thì cập nhật lại phương án tối ưu hoặc

đi tiếp theo hướng đó

+ Trong trường hợp ngược lại thì bỏ qua hướng đang xét

Trang 15

4.2 Giải quyết bài toán cụ thể bằng phương pháp nhánh cận

4.2.1 Phát biểu bài toán

Bài toán cái túi 0-n.

Có một tên trộm mang theo một cái túi có thể đựng trọng lượng tối đa

là M vào một cửa hàng có n loại đồ vật, mỗi loại đồ vật có một giá trị (v) vàtrọng lượng (w) riêng (giả sử số lượng mỗi đồ vật là rất nhiều) Hỏi tên trộmchọn những loại đồ vật nào với số lượng bao nhiêu để tổng trọng lượng khôngvượt quá trọng lượng tối đa của cái túi (M) và tổng giá trị của các đồ vật (V)

là lớn nhất ?

4.2.2 Trình bày thuật toán

Áp dụng kỹ thuật nhánh cận để giải bài toán.

Ký hiệu : w[i] là trọng lượng của loại đồ vật i (i = 1 n) v[i] là giá trịcủa loại đồ vật i (i = 1 n) Mô hình bài toán có thể đưa về dạng bài toán quyhoạch tuyến tính nguyên tìm vectơ x = [ x1 , , xn ] ( với x1, , , xn là sốlượng loại đồ vật 1, ,n được chọn ) như sau:

Hàm mục tiêu : f = v1*x1 + … + vn*xn  max Hệ ràng buộc :

w1*x1 + + wn*xn ≤ M

xi ≥ 0 ( i =1 n)

Để đánh giá giá trị của đồ vật so với trọng lượng ta dùng hệ số giá trị :vi/wi ( i = 1 n) Ưu tiên các đồ vật có hệ số giá trị lớn chọn trước nên ta sắpxếp các loại đồ vật từ cao đến thấp theo hệ số giá trị

Trang 16

Tương tự quá trình thiết lập nhánh và cận trên cứ lặp lại cho tới khinào không thể chọn thêm một đồ vật nào nữa (túi không thể chứa thêm đồvật nào nữa) Để tìm phương án tối ưu ta đi theo nhánh có cận lớn nhất Kýhiệu : a : giá trị đồ vật đang đạt được, b: cận trên của nhánh, M’ là trọnglượng còn lại Bài toán biểu diễn theo cấu trúc cây như sau:

………

Thuật toán:

Input: n, m; //số vật và trọng lượng tối đa túi có thể mang

W[i], V[i]; //Trọng lượng và giá trị của vật thứ i;

wrem; Trọng lượng túi còn có thể chứa;

vsel, wsel; Giá trị sử dụng và trọng lượng túi đang chứa;

Output: FOPT; //Giá trị tối đa

XOPT; //Phương án tương ứng

Int X[MAX],XOPT[MAX],W[MAX],V[MAX],n,m,wrem,a=0,vsel=0,wsel=0,FOPT=0; float b;

void Try(int i){

….

Tất cả phương án a=0, M’=M b=M’*v1/w1

a=a+v1*k1 M’=M’-w1*k1

x 1=k1

x 2=k2

Ngày đăng: 24/03/2017, 08:10

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w