Cong ty Cong Nghe Tin hoc Nha truong http://www.vnschool.net
Bao lồi - Phương pháp Graham - Loại bỏ phần trong
25/04/2008

Như chúng ta đã biết, thường thì các thuật toán hình học thì khó phân tích hơn các thuật toán trong những lĩnh vực khác. Vì khó mô tả được đặc điểm của đầu vào (và đầu ra) hơn. Bài này, là một trong những thuật toán hình học rất hay mà không hề khó hiểu. Gramham là phương phám đáng chú ý vì hầu hết các tính toán dành cho việc sắp xếp: thuật toán có chứa một sắp xếp không tốn kém lắm. Thuật toán bắt đầu bằng việc xây dựng một đa giác đơn khép kín từ các điểm đã cho. Việc xây dựng này dùng một hàm: sắp các điểm theo khoá là giá trị của hàm theta (chúng ta sẽ xét cụ thể trong bài) tương ứng với góc giữa trục hoành và đường thẳng nối mỗi điểm chốt p[1] (điểm có tung độ nhỏ nhất), và khi lần theo p[1], p[2],…, p[N], p[1] ta sẽ được một đa giác khép kín.


Bao lồi được tìm bằng cách đi vòng: thử đặt một điểm vào bao và kiểm tra các điểm trước đấy có còn thuộc bao hay không. Ví dụ, ta xét các điểm theo thứ tự B M J L N P K F I E C O A H G D; ta có các bước đầu tiên được bắt đầu như sau:

Khi bắt đầu, ta biết B, M thuộc bao. Khi xét J, nó được đưa vào bao và tạo thành hình tam giác. Tiếp đó, khi xét đến L, ta nhận thấy rằng J không thể thuộc bao (vì J lọt trong tam giác BML).

Dễ dàng kiểm tra để loại một điểm khỏi bao. Sau khi thêm vào một điểm, ta sẽ lần quanh các điểm đã đưa vào bao và xét xem có loại điểm nào hay không. Khi lần quanh bao, ta chờ sự quẹo trái ở mỗi đỉnh của bao. Tại điểm mới thêm, nếu có quẹo phải, thì ta loại điểm này vì đa giác lồi đang có đã chứa trong điểm vừa thêm. Giả sử khi ta xét các điểm p[1…i-1], ta đã xác định được p[1…M] là bao. Khi xét điểm mới p[i], nếu ccw(p[M], p[M-1], p[i]) là không âm, ta loại p[M] ra khỏi bao. Nếu không , p[M] vẫn thuộc bao.

Hình trên cho thấy quá trình thực hiện cách xử lý này trên tập điểm. Mỗi điểm mới được xử lý như sau: điểm mới này được đưa vào bao và dùng làm ‘nhân chứng’ cho việc loại bỏ các điểm có sẵn trên bao. Sau khi L, N, P được thêm vào bao, P bị loại bỏ khi xét tới K (vì NPK là một quẹo phải), rồi F và I được thêm vào. Khi xét E, điểm I bị loại vì FIE là một quẹo phải; … Như vậy sẽ có nhiều hơn một điểm bị loại khi xét một điểm mới. Tiếp tục theo cách này, sau cùng thuật toán của chúng ta sẽ quay về điểm B.

Sự sắp xếp ban đầu đảm bảo mỗi điểm được xét lần lượt đều có khả năng thuộc bao, vì mọi điểm được xét trước đó có giá trị theta nhỏ hơn. Mỗi đường thẳng nối p[1] và p[i], tồn tại các phép loại trừ, có tính chất là một điểm được xét trước đó đều nằm về cùng một phía của đường thẳng này. Vì vậy khi xét tới điểm p[N] (cũng phải thuộc bao do thứ tự sắp xếp), ta đã tìm đủ các điểm trên bao.

Trong phương pháp bọc - gói ta đã xét ở số trước, các điểm trên cùng một cạnh của bao có thể được hoặc không được nhắc đến dù có tới 2 trường hợp đối với các điểm cộng tuyến. Trước tiên, nếu có 2 điểm cộng tuyến với p[1] thì việc sắp xếp dùng hàm theta có thể hoặc không thể lấy chúng theo thứ tự của chúng trên đường thẳng chung. Các điểm không đúng trật tự sẽ bị loại trong quá trình quét. Thứ hai, có thể xuất hiện các điểm cộng tuyến trên các bao thử nghiệm (tất nhiên không thể khử các điểm này)

Chúng ta sẽ cần chú ý một số chi tiết khi cài đặt thuật toán này dù rằng nó không có gì phức tạp. Ban đầu, điểm có giá trị x lớn nhất trong các điểm số điểm có y nhỏ nhất được đổi chỗ với p[1]. Sau đó shellsort được dùng để sắp lại các điểm (chúng ta có thể dùng bất kỳ cách sắp xếp nào cũng được), bằng cách dùng giá trị theta của các điểm này với p[1]. Sau khi sắp, p[N] được chép vào p[0] để làm biến cầm canh trong trường hợp p[3] không thuộc bao. Sau cùng, tiến hành việc quét như đã nói trên. Chương trình sau tìm bao lồi của tập điểm p[1…N]

vòng lặp lưu giữ bao mảng p[1..M]. Với mỗi giá trị i đang xét, M được giảm nếu có các điểm bị loại khỏi bao, sau đó đưa p[i] vào bao bằng cách đổi chỗ với p[M+1]. Hình sau cho thấy nội dung của mảng p sau mỗi lần xét một điểm mới.

Thuật toán này lý thú ở chỗ nó là một dạng đơn giản của backtracking – kỹ thuật thiết kế thuật toán kiểu “thử làm một điều gì đó, nếu không thành công thì lại thử lại một lần khác”.

Loại bỏ phần trong

Hầu như mọi phương pháp tìm bao lồi có thể cải tiến được nhiều bằng cách dùng một kỹ thuật đơn giản để nhanh chóng loại bỏ ngay từ đầu phần lớn tập điểm. Ý tưởng tổng quát rất đơn giản: lấy 4 điểm đã biết trên bao, rồi bỏ đi một điểm bên trong tứ giác do 4 điểm trên tạo thành. Điều này làm giảm khá nhiểu số điểm phải xét, sau đó các điểm còn lại được xử lý bằng quét Graham hay kỹ thuật bọc – gói.

Bốn điểm đã biết trên biên nên đươc chọn theo các thông tin về tập điểm đã cho. Nói chung, việc chọn tối ưu phải phù hợp với sự phân bố các phần tử của tập điểm đã cho. Trong hai tập điểm ví dụ trên hình dưới đây cho thấy kỹ thuật này loại bỏ đa số các điểm không thuộc biên.

Khi cài đặt việc loại bỏ phần trong, có một vòng lặp để kiểm tra mỗi điểm của tập điểm đã cho có nằm trong tứ giác kiểm tra hay không. Tốc độ thuật toán có thể tăng nhanh hơn một chút bằng cách dùng một hình chữ nhật có các cạnh song song với trục x và y. Đó là hình chữ nhật lớn nhất chứa trong tứ giác nói trên. Ta dễ dàng tìm tọa độ 4 đỉnh của hình chữ nhật này từ các tọa độ đỉnh của tứ giác trên. Dùng hình chữ nhật này, số điểm trong bị loại ít hơn, nhưng làm tốc độ kiểm tra nhanh hơn.

Kết quả khi thực hiện thuật toán

Như chúng ta đã biết, thường thì các thuật toán hình học thì khó phân tích hơn các thuật toán trong những lĩnh vực khác. Vì khó mô tả được đặc điểm của đầu vào (và đầu ra) hơn. Các thuật toán hình học phụ thuộc vào đặc điểm phân bố của các điểm và như vậy không thể so sánh các thuật toán với nhau; bởi vì sự so sánh chúng yêu cầu có một sự hiểu biết về các tác động qua lại phức tạp giữa các đặc tính được hiểu biết ít ỏi của các tập điểm. Nhưng cũng có vài điều về việc thực hiện các thuật toán trên, giúp chúng ta chọn lựa thuật toán thích hợp trong các ứng dụng cụ thể

*** Sau khi sắp xếp, quét Gramham là một tiến trình có thời gian tuyến tính

Chúng ta sẽ cùng suy nghĩ để chứng minh tính chất trên là đúng, vì có một “vòng lặp trong vòng lặp” trong chương trình. Tuy nhiên, để thấy rằng không điểm nào bị “loại bỏ” hơn một lần, như vậy phần mã trong vòng lặp được lặp lại ít nhất N lần. Thời gian tổng cộng để tìm bao lồi bằng phương pháp này là : O(NlogN), nhưng vòng lặp trong tự bản thân nó là một phép sắp xếp, có thể được làm hiệu quả hơn những phương pháp khác.

**** Nếu bảo có M đỉnh, thì thuật toán bọc – gói yêu cầu khoảng MN bước lặp.

Đầu tiên, ta phải tính N-1 góc để tìm góc nhỏ nhất, lần lặp kế tiếp cần N-2, rồi N-3,… như vậy tổng cộng số phép tính góc là: (N-1)+ (N-2)+…+ (N-M+1) = MN – M(M-1)/2

Như vậy ta có thể thấy rằng: Phép loại bỏ phần trong là tuyến tính về thời gian trung bình

Tìm bao lồi và các thuật toán tìm kiếm
URL của bài viết này::http://www.vnschool.net/modules.php?name=News&file=article&sid=1999
© Cong ty Cong Nghe Tin hoc Nha truong contact: sales@schoolnet.vn