§a sè c¸c thuËt to¸n ®Òu tËp trung xö lÝ trªn v¨n b¶n (xö lÝ trªn x©u) vµ c¸c con sè, chóng ®îc thiÕt kÕ vµ xö lÝ s½n trong phÇn lín c¸c bµi to¸n lËp tr×nh. §èi víi c¸c bµi to¸n h×nh häc th× ®ßi hái kh¸c h¼n, ngêi lËp tr×nh ph¶i cã sù tÝnh to¸n tØ mØ c¸c c«ng thøc vÒ h×nh häc tríc khi ®i vµo lËp tr×nh. Khi lµm c¸c bµi tËp vÒ h×nh häc thêng ph¶i ®ßi hái sù c«ng phu lËp tr×nh h¬n c¸c bµi tËp kh¸c, nhÊt lµ viÖc thiÕt lËp c¸c c«ng thøc th× bµi lËp tr×nh míi cã hiÖu qu¶. 1. §èi tîng h×nh häc c¬ b¶n Trong c¸c bµi to¸n Tin häc thuéc lo¹i h×nh häc cã 3 ®èi tîng c¬ b¶n lµ: §iÓm, §o¹n th¼ng vµ §a gi¸c. §iÓm: §îc xÐt b»ng mét cÆp sè nguyªn lµ täa ®é cña ®iÓm ®ã trong hÖ trôc täa ®é Descartes thêng dïng. §o¹n th¼ng: Lµ mét cÆp ®iÓm ®îc nèi víi nhau mét phÇn cña ®êng th¼ng. §a gi¸c: Lµ mét d•y c¸c ®iÓm víi hai ®iÓm liªn tiÕp ®îc nèi bëi mét ®o¹n th¼ng, vµ ®iÓm ®Çu ®îc nèi víi ®iÓm cuèi t¹o thµnh mét h×nh gÊp khóc khÐp kÝn. 2. D÷ liÖu lu tr÷ c¸c ®èi tîng h×nh häc c¬ b¶n Lµm viÖc víi c¸c ®èi tîng h×nh häc chóng ta cÇn quyÕt ®Þnh thÓ hiÖn chóng nh thÕ nµo? Th«ng thêng ta dïng mét m¶ng ®Ó biÓu diÔn mét ®a gi¸c, dï r»ng mét sè trêng hîp kh¸c chóng ta cã thÓ dïng danh s¸ch liªn kÕt hay c¸c kiÓu kh¸c. §èi tîng chóng ta thêng xuyªn ph¶i lµm viÖc víi h×nh häc lµ täa ®é, do ®ã viÖc lu tr÷ to¹ ®é cña c¸c ®iÓm lµ phæ biÕn trong c¸c bµi to¸n lËp tr×nh vÒ h×nh häc.
BÀI TỐN CẶP ĐIỂM GẦN NHẤT I Mở đầu §a số thuật toán tập trung xử lí văn (xử lí xâu) số, chúng đợc thiết kế xử lí sẵn phần lớn toán lập trình Đối với toán hình học đòi hỏi khác hẳn, ngời lập trình phải có tính toán tỉ mỉ công thức hình học trớc vào lập trình Khi làm tập hình học thờng phải đòi hỏi công phu lập trình tập khác, việc thiết lập công thức lập trình có hiệu Đối tợng hình học Trong toán Tin học thuộc loại hình học có đối tợng là: Điểm, Đoạn thẳng Đa giác Điểm: Đợc xét cặp số nguyên tọa độ ®iĨm ®ã hƯ trơc täa ®é Descartes thêng dïng Đoạn thẳng: Là cặp điểm đợc nối với phần đờng thẳng Đa giác: Là dÃy điểm với hai điểm liên tiếp đợc nối đoạn thẳng, điểm đầu đợc nối với điểm cuối tạo thành hình gấp khúc khép kín Dữ liệu lu trữ đối tợng hình học Làm việc với đối tợng hình học cần định thể chúng nh nào? Thông thờng ta dùng mảng để biểu diễn đa giác, số trờng hợp khác dùng danh sách liên kết hay kiểu khác Đối tợng thờng xuyên phải làm việc với hình học tọa độ, việc lu trữ toạ độ điểm phổ biến toán lập trình hình học II Nội dung Phát biểu toán Bài toán: Cho điểm mặt mẳng tọa độ, tìm khoảng cách ngắn hai điểm Thuật toán Bài tốn ta dễ dàng thực thuật toán , ta xét tất cặp điểm chọn cặp có khoảng cách ngắn chúng Thuật tốn có độ phức tạp Ta có số thuật toán tốt sau: 2.1.Thuật toán chia để trị a Ý tưởng thuật toán Thuật toán chia để trị giải toán thực sau: • Sắp xếp điểm cho theo thứ tự từ trái sang phải Chia tập điểm thành hai tập • Thực thao tác đệ quy, tìm cặp điểm gần hai tập con, trả lại giá trị khoảng cách ngắn tập • Gọi khoảng cách ngắn nhất, hai khoảng cách ngắn hai tập Ta quan tâm tới cặp có khoảng cách nhỏ • Xét “cửa sổ” độ rộng , xếp tất điểm cửa sổ theo thứ tự tăng dần chiều tọa độ • Nhận xét: khoảng cách cặp điểm hai tập không nhỏ nên với điểm “cửa sổ”, có khơng q điểm bên có khoảng cách nhỏ so với điểm Do vậy, với điểm, ta cần xét (ghép cặp) khơng q điểm để tìm cặp điểm có khoảng cách Euclid nhỏ b Cài đặt Sử dụng đệ quy quay lui để cài đặt thuật tốn Với đoạn: • Nếu độ dài đoạn , ta tính tốn bruteforce để tìm cặp điểm gần Nếu độ dài ta chia đôi tập, đệ quy quay lui để tính khoảng cách gần • hai tập con, chọn giá trị bé hai khoảng cách Dùng mảng để trộn hai phía theo thứ tự tăng dần , lọc lấy • phần tử có chênh lệch nhỏ giá trị có () Chú ý sau thực hiện, ta thực xếp trộn hai phía đoạn theo thứ tự tăng dần y luôn, độ phức tạp , không sử dụng thuật tốn xếp • khác Với phần tử cửa sổ, với điểm, xét điểm lân cận (sau xếp) có chênh lệch nhỏ (số phần tử Dưới chương trình cài đặt tính cặp điểm gần nhấttheo thuật tốn chia để trị: Input: • Dịng số – số lượng điểm • dịng tiếp theo, dòng chứa tọa độ điểm theo thứ tự Output: Khoảng cách nhỏ cần tìm, xác chữ số phần thập phân CLOSESTPAIR.INP 1 2 CLOSESTPAIR.OUT 1.00000 Chương trình: #include #define sz(x) int(x.size()) #define MIN(x,y) if (x < y) x = y #define PB push_back #define mp make_pair #define Task "closestpair" #define maxn 200002 #define MOD 1000000007 #define remain(x) if (x > MOD) x -= MOD #define pii pair #define X first #define Y second using namespace std; pii a[maxn], strip[maxn]; double ans = 1e10; double Distance(pii P1, pii P2) { double XX = P1.X - P2.X; double YY = P1.Y - P2.Y; return sqrt(XX*XX + YY*YY); } double bruteForce(pii P[], int n) { double kmin = FLT_MAX; for (int i = 0; i < n; i++) for (int j = i+1; j < n; j++) kmin = min(kmin, Distance(P[i], P[j])); return kmin; } bool compareY(pii p1, pii p2) { return (p1.Y < p2.Y || (p1.Y == p2.Y && p1.X < p2.X)); } double stripClosest(pii strip[], int n, double d) { double kmin = d; for (int i = 0; i < n; ++i) for (int j = i+1; j < n && (strip[j].Y - strip[i].Y) < kmin; j++) kmin = min(Distance(strip[i],strip[j]), kmin); return kmin; } double Calc(pii P[], int n) { if (n > n; for (int i = 0; i < n; i++) cin >> a[i].X >> a[i].Y; printf("%0.5f", Closest(a,n)); return 0; } c Đánh giá Việc tính cửa sổ xếp trộn với đoạn độ dài (khơng tính hai đoạn con) có độ phức tạp O(n) Số lần lặp thủ tục tính có lời gọi khơng q lần nên tổng độ phức tạp thuật toán 2.2.Thuật toán sweep line a Ý tưởng thuật tốn • Sắp xếp tọa độ điểm theo chiều • Xét điểm từ trái qua phải Giả sử ta xét tới điểm giá trị nhỏ hai điểm điểm bên trái Rõ ràng ta giữ lại điểm có khoảng cách tới tọa độ (hình trái) • Với điểm ta cần xét điểm có chênh lệch so với khơng (hình bên phải) Dễ thấy, khoảng cách ngắn điểm tập điểm bên trái xét nên chắn có khơng b q điểm Cài đặt Sử dụng thêm cấu trúc set để lưu trữ phần tử “vệt quét” hay nói cách khác phần tử có tọa độ x có khoảng cách tới tọa độ x p xét nhỏ giá trị d Đồng thời dễ ràng thêm, xóa tìm kiếm phần tử phạm vi Dưới chương trình cài đặt tính cặp điểm gần nhấttheo thuật tốn sweepline: #include #define sz(x) int(x.size()) #define MIN(x,y) if (x < y) x = y #define PB push_back #define mp make_pair #define F first #define S second #define Task "closestpair" #define maxn 200002 #define MOD 1000000007 #define remain(x) if (x > MOD) x -= MOD #define pii pair #define Y first #define X second using namespace std; pii a[maxn]; set S; double Distance(pii P1, pii P2) { double XX = P1.X - P2.X; double YY = P1.Y - P2.Y; return sqrt(XX*XX + YY*YY); } bool compareX(pii p1, pii p2) { return (p1.X < p2.X || (p1.X == p2.X && p1.Y < p2.Y)); } double Closest(pii a[], int n) { sort(a, a+n, compareX); S.insert(a[0]); int left = 0; double ans = 1e10; for (int i = 1; i < n; i++) { int py = a[i].Y; int px = a[i].X; while (a[left].X < px - ans) S.erase(a[left++]); for (set :: iterator it = S.lower_bound(mp(1.0*py-ans, 1.0*px-ans)); it != S.end() && it->Y < ans+py; it++) ans = (ans, Distance(*it, a[i])); S.insert(a[i]); } return ans; } int main() { ios_base::sync_with_stdio(0); freopen(Task".inp", "r", stdin); freopen(Task".out", "w", stdout); int n; cin >> n; for (int i = 0; i < n; i++) cin >> a[i].X >> a[i].Y; printf("%0.5f", Closest(a,n)); return 0; } c Đánh giá Mỗi điểm thêm vào xóa Set lần nên thời gian xử lí thêm vào xóa Set Với điểm việc tìm vị trí bắt đầu có tọa độ phạm vi (hàm lower-bound) chi phí thời gian Số điểm để thuộc hình chữ nhật xét ln khơng vượt q Do vậy, tổng độ phức tạp để thực giải thuật 10 III.Kết luận Với toán cặp điểm gần nhất, hai thuật toán chia để trị sweepline trình bày có độ phức tạp Việc cài đặt thuật toán sweepline cài đặt đơn giản, ngắn gọn (khi sử dụng ngôn ngữ C++) Tuy nhiên, mặt thời gian, thuật toán chia để trị lại thực hiệu việc xử lý Set C++ tốn nhiều thời gian Tài liệu tham khảo Thomas H.Cormen, Charles E Leiserson, Ronald L Rivest, Clifford Stein, Introduction To Algorithms, Third Edition Mark de Berg, Otfried Cheong, Marc van Kreveld, Mark Overmars, Computational Geometry Algorithms and Appliacitons, Third Edition 11 ... điểm phổ biến toán lập trình hình học II Nội dung Phát biểu toán Bài toán: Cho điểm mặt mẳng tọa độ, tìm khoảng cách ngắn hai điểm Thuật toán Bài tốn ta dễ dàng thực thuật toán , ta xét tất cặp. .. xét tất cặp điểm chọn cặp có khoảng cách ngắn chúng Thuật tốn có độ phức tạp Ta có số thuật toán tốt sau: 2.1.Thuật toán chia để trị a Ý tưởng thuật toán Thuật toán chia để trị giải toán thực... cửa sổ, với điểm, xét điểm lân cận (sau xếp) có chênh lệch nhỏ (số phần tử Dưới chương trình cài đặt tính cặp điểm gần nhấttheo thuật tốn chia để trị: Input: • Dịng số – số lượng điểm • dịng