so sánh giá trị của hai đối tượng nào đó thường phải xử lý dưới dạng số nguyênmáy tính so sánh hai số thực có khi không chính xác, hơn nữa trong tin họcviệc giải các bài toán hình học lạ
Trang 1MỤC LỤC 1
PHẦN 1 MỞ ĐẦU 2
1 LÝ DO CHỌN ĐỀ TÀI 2
2 MỤC ĐÍCH CỦA ĐỀ TÀI 2
3 ĐỐI TƯỢNG NGHIÊN CỨU CỦA ĐỀ TÀI 2
3 PHƯƠNG PHÁP NGHIÊN CỨU CỦA ĐỀ TÀI 2
PHẦN 2 NỘI DUNG 3
I – BIỂU DIỄN CÁC ĐỐI TƯỢNG CƠ BẢN CỦA HÌNH HỌC 3
I.1 Biểu diễn điểm, đoạn thẳng và đường thẳng 3
I.2 Kiểu dữ liệu số 3
II THUẬT TOÁN GIẢI MỘT SỐ BÀI TOÁN HÌNH HỌC CƠ BẢN 4
II.1 Tính toán hoặc so sánh độ dài của đoạn thẳng, chu vi, diện tích các hình 4
II.2 Vị trí tương đối giữa ba điểm liên tiếp A, B, C: 5
II.3 Phương trình đường thẳng 5
II.4 Vị trí tương đối giữa điểm và đường thẳng 6
II.5 Xác định điểm M có thuộc đoạn thẳng P 1 P 2 6
II.6 Xác định điểm M có thuộc tia AB 7
II.7 Xác định vị trí tương đối giữa 2 điểm M 1 ,M 2 so với đường thẳng p 1 p 2 7
II.8 Vị trí tương đối của 2 đường thẳng 8
II.8 Xác định 2 đoạn thẳng có giao nhau hay không 9
III MỘT SỐ BÀI TOÁN CƠ BẢN VỀ ĐA GIÁC 9
1 Một số định nghĩa 9
1.1 Đường gấp khúc 9
1.2 Đa giác 9
1.3 Đa giác tự cắt 9
1.4 Đa giác lồi 9
1.5 Định lý về bao lồi 10
2 Một số bài toán cơ sở: 10
2.1 Tính diện tích một đa giác 10
2.2 Kiểm tra đa giác lồi 10
2.3 Vị trí tương đối một điểm và đa giác 11
2.4 Tìm bao lồi có chu vi nhỏ nhất 14
PHẦN 3 KẾT LUẬN 19
Tài liệu tham khảo 20
PHỤ LỤC: MỘT SỐ BÀI TẬP VÍ DỤ 21
Trang 2so sánh giá trị của hai đối tượng nào đó thường phải xử lý dưới dạng số nguyên(máy tính so sánh hai số thực có khi không chính xác), hơn nữa trong tin họcviệc giải các bài toán hình học lại thiên về việc xử lý trên rất nhiều đối tượng vìvậy cách thức tổ chức dữ liệu, cách thức xây dựng công thức, phương pháp tínhtoán là những vấn đề cần hệ thống lại để xây dựng cho các em học sinh có cáchnhìn tổng quan về vấn đề này, giúp các em không bị rối khi lập trình giải các bàitoán hình học Tuy nhiên các tài liệu như sách giáo khoa Tin học, sách bài tậpTin học chưa đi sâu vào vấn đề này
Vì những lý do nói trên nên trong đề tài này tôi đã mạnh dạn trình bàynhững kinh nghiệm của mình tích lũy được trong quá trình giảng dạy về lậptrình giải các bài toán hình học, với mong muốn đề tài này có thể có ích cho họcsinh, bạn bè đồng nghiệp và những người yêu lập trình
3 ĐỐI TƯỢNG NGHIÊN CỨU CỦA ĐỀ TÀI
Các cấu trúc dữ liệu để biểu diễn các đối tượng hình học, các thuật toángiải các bài toán hình học cơ bản, một số bài toán hình học thường gặp và thuậttoán giải chúng
3 PHƯƠNG PHÁP NGHIÊN CỨU CỦA ĐỀ TÀI
- Xây dựng cơ sở lý thuyết
- Điều tra khảo sát thực tế, đối sánh
Trang 3PHẦN 2 NỘI DUNG
I – BIỂU DIỄN CÁC ĐỐI TƯỢNG CƠ BẢN CỦA HÌNH HỌC
I.1 Biểu diễn điểm, đoạn thẳng và đường thẳng
Như chúng ta đã biết, các khái niệm: điểm, đoạn thẳng, đường thẳng lànhững đối tường cơ bản nhất trong hình học nói chung Để biểu diễn các đốitượng nói trên trong tin học có nhiều cách khác nhau, tuy nhiên ta có thể sửdụng cách biểu diễn bằng các cấu trúc dữ liệu như sau:
//Đa giác, tập hợp điểm
Polygon = Array[1 MAXN] of Point
1 Để thuận lợi thì khi biểu diễn đa giác ta cũng có thể thêm hai đỉnh ở đầu
và cuối: đỉnh 0 bằng đỉnh n và đỉnh n + 1 bằng đỉnh 1
2 Điều cần lưu ý ở đây là ta có thể dùng hai biến đơn x, y để biểu diễn mộtđiểm, nhưng nếu như vậy khi càn biểu diễn một tập hợp nhiều điểm ta phải dùnghai mảng hoặc một mảng hai chiều, điều này sẽ không lợi khi phải sắp xếp cácđiểm này theo một thứ tự nào đó
I.2 Kiểu dữ liệu số
3 Trong các bài toán hình học, phần lớn các đối tượng đều được thể hiệntrên hệ trục tọa độ Descartes, việc biểu diễn các thành phần tọa độ có thể sửdụng cả kiểu số thực và kiểu số nguyên của ngôn ngữ lập trình Một số kiểu dữliệu của Pascal hay sử dụng
4 + Kiểu số nguyên:
Trang 4II THUẬT TOÁN GIẢI MỘT SỐ BÀI TOÁN HÌNH HỌC CƠ BẢN
II.1 Tính toán hoặc so sánh độ dài của đoạn thẳng, chu vi, diện tích các hình
Đối với đoạn thẳng, việc tính toán hay so sánh độ dài của đoạn thẳng nàyvới đoạn thẳng khác dựa trên tọa độ sẽ không thể thực hiện được một cách chínhxác nếu như trong công thức có xuất hiện dấu căn Thay vào đó ta phải viết biếnđổi công thức toán học thành một dạng khác sao cho không còn xuất hiện dấucăn thức
- Để so sánh độ dài của hai đoạn thẳng, đoạn thẳng thứ nhất nối giữa hai
điểm M1(x1; y1) , M2(x2;y2) và đoạn thẳng thứ hai nối giữa hai điểm M3(x3; y3), 4(x4;y4).
Trang 5M-7 Function EQA (x,y : doan) : boolean;
17 - Điều kiện 3 điểm A(XA,YA), B(XB,YB), C(XC,YC) thẳng hàng:
(XA-XB)*(YA-YC) = (XA-XC)(YA-YB)
II.2 Vị trí tương đối giữa ba điểm liên tiếp A, B, C:
18 Có 3 khả năng xảy ra:
22 Khi lập trình ta có thể dùng hàm như sau:
23 Function CCW (A,B,C : point) : integer;
25 If (B.x - A.x)*(C.y - B.y) - (B.y - A.y)*(C.x-B.x)= 0 then exit(0);
26 If (B.x - A.x)*(C.y - B.y) - (B.y - A.y)*(C.x-B.x)< 0 then exit(1)
27 Else exit(-1);
Trang 629 End;
30
II.3 Phương trình đường thẳng
31 Phương trình đường thẳng đi qua hai điểm phân biệt P1, P2 có dạng:
f(x,y) = (x- P 1 x)*(P 2 y – P 1 y) - (y – P 1 y)*(P 2 x – P 1 x) = 0.
32 Viết dưới dạng tổng quát : f(x,y) = Ax + By + C = 0 như sau:
33 f(x,y)=(P 2 y – P 1 y) x +(P 1 x – P 2 x) y +((P 2 x – P 1 x)*P 1 y - (P 2 y – P 1 y)*
II.4 Vị trí tương đối giữa điểm và đường thẳng
40 Cho 3 điểm P1, P2, M, Vị trí tương đối giữa M và so với vector p p1, 2
, xácđịnh như sau:
41 VT := (p2.x-p1.x)(M.y-p1.y)-(p2.y-p1.y)(M.x-p1.x);
42 - Nếu VT>0 thì M bên trái véctơ p p1 , 2
43 - Nếu VT<0 thì M bên phải véctơ p p1 , 2
44 - Nếu VT=0 thì M nằm trên đường thẳng chứa véctơ p p1 , 2
45 Function PoInLn (p1,p2,M : point) : integer;
46 Var temp : longint;
48 49 Temp:=(p2.x-p1.x)*(M.y-p1.y)-(p2.y-p1.y)*(M.x-p1.x);
50 If Temp = 0 then exit(0);
Trang 751 52 If Temp > 0 then exit(1) Else exit(-1);
53 End; { hàm = 1 thì M bên trái p p1, 2, hàm = -1 thì M bên phải}
II.5 Xác định điểm M có thuộc đoạn thẳng P1P2
54 M thỏa 2 điều kiện sau:
55 - M nằm trên đường thẳng p1p2
56 - Tọa độ M thỏa : (M.x>=min(p1.x,p2.x)) and (M.x<=max(p1.x,p2.x)) and(M.y>=min(p1.y,p2.y)) and (M.y<=max(p1.y,p2.y)))
57 Function PoInLi (p1,p2,M : point) : boolean;
58 Var temp : longint;
II.6 Xác định điểm M có thuộc tia AB
64 Điểm M thuộc tia AB nếu M thuộc đường thẳng AB và AM k AB.
với k
≥0:
65 f(M.x,M.y)=0, (M.x-A.x)( B.x-A.x)>=0 và (M.y-A.y)( B.y-A.y)>=0
66 Function PinRay (p1,p2,M : point) : boolean;
67 Var temp : longint;
Trang 8II.7 Xác định vị trí tương đối giữa 2 điểm M1,M2 so với đường thẳng p1p2
75 Function Po2PoLi (p1,p2,M1,M2 : point) : boolean;
76 Var temp1, Temp2 : longint;
78 79 Temp1:= PoInLi (p1,p2,M1 : point);
80 Temp2:= PoInLi (p1,p2,M2 : point) ;
81 82 Exit(Temp1 *Temp2 >= 0);
83 End; { hàm = true thì M1, M2 cùng phía, ngược lại thì khác phía}
II.8 Vị trí tương đối của 2 đường thẳng
84 Cho 4 điểm A, B, C, D Vị trí tương đối giữa 2 đường thẳng qua 2 điểm
AB và qua 2 điểm CD được xác định như sau:
85 - Tính hệ số A1, B1, C1 của đường thẳng AB
86 - Tính hệ số A2, B2, C2 của đường thẳng CD
87 - Tính 1 1
2 2
a b d
a c
88 - Nếu D<>0 thì cắt nhau
89 - Ngược lại
0 - Nếu (dx=0) and (dy=0) thì trùng nhau - Ngược lại song song.
90 Function Pos2Li(var I:Point;A,B,C,D: Point): integer;
91 Var a1, b1, c1, a2, b2, c2:real; d, dx, dy: real;
Trang 999 If (d = 0) then
100 101 If (dx= 0) and (dy= 0) then exit(0) // trùng nhau
102 103 Else exit(-1) // song song
II.8 Xác định 2 đoạn thẳng có giao nhau hay không
113 Hai đoạn thẳng giao nhau nếu thỏa điều kiện:
0 - Hai đường thẳng qua 2 điểm đó phải cắt nhau tại một điểm I
1 - Và I thuộc 2 đoạn thẳng
2 Cần lưu ý điều kiện thứ hai, có nhiều học sinh hay bỏ sót điều kiện này
114 Function Intersect1(A,B,C,D: Point; var I:Point): boolean;
Trang 101.4 Đa giác lồi
1 Một đa giác lồi được gọi là lồi nếu đa giác luôn nằm cùng một phía đốivới đường thẳng đi qua một cạnh bất kỳ Đa giác lồi là đa giác không tự cắt
1.5 Định lý về bao lồi
2 Với một tập hữu hạn M các điểm trên mặt phẳng(có ít nhất 3 điểm không thẳng hàng) ta luôn tìm được một tập con H của M sao cho H là tập các đỉnh của đa giác lồi P mà mọi điểm của M đều thuộc đa giác này.
2 Một số bài toán cơ sở:
2.1 Tính diện tích một đa giác
2.2 Kiểm tra đa giác lồi
Kiểm tra dựa theo định nghĩa:
Trang 11127 Function Convex (P:polygon;n:longint):boolean;
128 Var i,j,l,k:longint;
130 For i:=1 to n do
131 Begin
132 133 l:=i+1; if l=n+1 then l:=1; // đỉnh kế với i
134 k:=i+2; if l=n+1 then k:=1; // đỉnh xét cùng phía
135 for j:=1 to n do // vét tất cả các đỉnh //
136 if (j<>i) and (j<>k) and
137 (j<>l) and (not Pos2PoLi(P[i],P[l],P[k],P[j]))
138 then exit(false);
141 142 exit(true);
2.3 Vị trí tương đối một điểm và đa giác
+ Đối với đa giác lồi
Điểm thuộc đa giác nếu điểm nằm trên các cạnh hoặc thuộc miền đa giác
Ta thấy nếu xét các cạnh của đa giác theo 1 chiều nào đó thì điểm M thuộc
đa giác nếu nằm cùng 1 bên (trái hoặc phải) với mọi vector cạnh cuả đa giác
Trang 12144 Function Inside (P:polygon;n:longint;M:point):boolean;
145 Var i:longint; VT, VT1:integer;
Trang 13- Vẽ trục song với trục tung với tọa độ x=max{các hoành độ}+1.
- Vẽ đoạn thẳng song song với trục hoành và cắt trục vẽ bên trên Ta nhậnxét nếu số giao điểm với đa giác là số lẻ thì điểm thuộc đa giác Còn ngược lạiđiểm nằm ngoài đa giác
- Các trường hợp cắt sau ta chỉ tính cắt tại 1 giao điểm:
157 Function Inside (P:polygon;n:longint;M:point):boolean;
158 Var I,count:longint; I,N point; xmax:real;
160 P[n+2]:=P[2]; // phần tử cầm canh Ta có sẵn P[0]:=P[n],
P[n+1]:=P[1]
161 Count:=0; // đếm số giao điểm
162 xmax:=findxmax(P); // tìm hoành độ lớn nhất của đa giác
163 N.x:=xmax+1; // điểm N
164 N.y:=M.y;
165 For i:=1 to n do
166 Begin
167 If PoInLi(P[i],P[i+1],M) then exit(true); // M thuộc cạnh
168 If not PoInLi(M,N,P[i]) then
169 Begin
170 If (not PoInLi(M,N, P[i+1])) and
(Intersect(M,N,P[i],P[i+1],I))
Trang 14171 then inc(count) // trường hợp 3
172 Else if not PoInLi(M,N, P[i+2]) and (not
2.4 Tìm bao lồi có chu vi nhỏ nhất
Bài toán: Cho tập M gồm N điểm phân biệt.Tìm tập con H của M sao cho H
là tập các đỉnh của đa giác lồi chứa tất cả các điểm của M trong miền đa giác đó
.
2.4.1 Thuật toán bọc gói
Đây là một giải thuật rất “con người” Bắt đầu bằng việc chọn một điểmchắc chắn thuộc bao, dùng một tia quét ngược chiều kim đồng hồ cho đến khigặp một điểm khác, ta được thêm một đỉnh thuộc bao, lại tiếp tục với điểm vừatìm được…Quá trình kết thúc khi gặp lại đỉnh đầu tiên
Có nhiều cách chọn điểm đầu tiên, một trong cách đó là ta chọn điểm cóhoành độ nhỏ nhất trong các điểm có tung độ nhỏ nhất
Một điều đáng chú ý ở đây là việc quét một tia ngược theo chiều kim đồng
hồ để tìm điểm đầu tiên chạm phải thực chất là ta tìm điểm mà tia nối từ điểmgốc tới nó tạo với trục hoành một góc bé nhất (điều này khá dễ hiểu) Vì vậychúng ta cũng cần phải biết cách tính góc khi cho điểm gốc và điểm cần xét đã.Nhưng chỉ với việc sắp xếp (tìm góc nhỏ nhất) thôi mà phải làm phức tạp đếnvậy thì thật là uổng công Ta có thể đưa ra một thứ tự hoàn toàn giống với việctính góc cụ thể mà chương trình thì đơn giản hơn nhiều:
function Angle(p1, p: Point): Real;
var
dx, dy, ax, ay, t: Real;
begin {p là điểm gốc}
Trang 15p[n + 1] := t; {để phát hiện thời điểm kết thúc}
m := 0; {m sẽ là số điểm trên bao}
Trang 16for i := m + 1 to n + 1 do
begin
tmp := Angle(p[i], p[m]);
if (tmp < min) or ((tmp = min) and
(Abs(t.x–p[m].x) < Abs(p[i].x–p[m].x))) then
begin {nếu nhiều điểm thoả mãn, chọn điểm ở xa nhất}
2.4.2.Thuật toán Grahamscan
Thuật toán bọc gói đòi hỏi một chi phí là O(M*N) (trong đó M là số điểmtrên bao) Vì vậy nó chỉ làm việc tốt trong trường hợp số điểm nằm trên bao nhỏhơn nhiều so với tổng số Nhưng trong trường hợp xấu nhất (tất cả mọi điểm đềunằm trên bao) thì chi phí thuật toán sẽ lên tới O(N2) Chúng ta sẽ tiếp cận mộtphương pháp tốt hơn – phương pháp quét Graham Phương pháp này có chi phíthuật toán ổn định và không tốn kém lắm Hầu như tất cả chi phí là dành choviệc khởi một tạo đường khép kín đơn từ tập điểm đã cho
Chọn điểm chốt có hoành độ x lớn nhất trong các điểm có tung độ y nhỏ
nhất (khi hiểu rõ thuật toán các bạn sẽ biết được nguyên nhân) Chuyển điểmchốt về vị trí 1 để tiện cho tính toán Ta sắp xếp các điểm theo khoá là góc tạobởi điểm đó và điểm chốt với trục hoành theo thứ tự tăng dần Khi đi theo thứ tựp[1], p[2], …p[N], p[1] ta thu được một đa giác khép kín đơn
Ta đi vòng quanh đa giác này, thử đặt một điểm vào bao và kiểm tra xemcác điểm trước đó có còn nằm trên bao hay không Nếu không ta chỉ việc loạicác điểm đó ra khỏi bao.Việc kiểm tra một điểm có còn nằm trên bao hay không
có thể làm như sau: Khi cho một điểm mới vào bao, ta sẽ lần ngược lại nhữngđiểm đã nằm trong bao Trong quá trình, nếu gặp một điểm là khúc rẽ phải thìđiểm này sẽ không thuộc bao nữa, ta loại nó luôn Quá trình kết thúc khi ta gặpmột điểm là khúc rẽ trái, vì tất cả các điểm từ đó lùi về 1 chắc chắn sẽ thuộc bao
Trang 17Cài đặt không phải là một vấn đề khó nhưng phải cảnh giác với sai số vàcác điểm thẳng hàng
Việc xây dựng đường khép kín đơn không thực sự phải dùng hàm Angle vì
dễ gây sai số và chi phí hơi lớn Vì tất cả các tia tạo bởi điểm chốt và một điểmbất kỳ đều trong góc phần tư I và II nên ta có thể dùng hàm Lower sau để làmphép so sánh cho việc sắp xếp
function Lower(p1, p2: Point): Boolean;
Sau đây là đoạn chương trình miêu tả phương pháp quét Graham Ta coi
mọi công việc khởi tạo đã xong xuôi Hàm CCW đã nói tới ở phần trước.
Trang 18Chi phí cho thủ tục trên tỷ lệ thuận với N Đúng vậy, mặc dù trong vònglặp có một vòng lặp, nhưng ta để ý là không điểm nào bị loại quá một lần nênvòng lặp này chỉ hoạt động không đến N lần.
Như vậy chi phí cho thuật toán này là O(NlogN) nếu ta dùng phươngpháp sắp xếp tốt (như Quick Sort chẳng hạn)
Ta có thể làm giảm chi phí tính toán đi rất nhiều bằng cách loại bỏ nhữngđiểm chắc chắn không thuộc bao
Ví dụ như ta loại đi những điểm nằm hoàn toàn trong tứ giác có các đỉnh
là các điểm có hoành độ lớn nhất, hoành độ nhỏ nhất, tung độ lớn nhất, tung độnhỏ nhất Đối với những bộ dữ liệu được tạo một cách ngẫu nhiên thì việc nàyrất có ích Nhưng nếu tất cả các điểm đều thuộc bao thì việc này là vô nghĩa Nóichung mọi cách tham lam thì cũng đều tốt trong một số trường hợp nhất định màthôi
Trang 19để các em học sinh luyện tập rèn luyện kỹ năng lập trình Mục III trình bàythuật toán giải một số bài toán cơ bản về đa giác Việc lập trình giải các bài toánhình học thường là vấn đề đòi hỏi học sinh phải chịu khó, cẩn thận và nắm đượcnhững kiến thức cơ bản về hình học và thường là khó đối với học sinh Tuynhiên nếu thầy cô có phương pháp tốt để học sinh tích cực, chủ động lĩnh hộiđược các kiến thức, chủ động rèn luyện kỹ năng kỹ xảo thì việc giải các bàitoán này sẽ trở nên dễ dàng hơn đối với học sinh
Qua quá trình giảng dạy môn Tin học cho các đối tượng học sinh bậc THPT
cả chuyên và không chuyên, khi dạy về phần lập trình giải các bài toán hình họctôi đều cung cấp cho các em các kiến thức như đã trình bày trong đề tài (mức độ
có khác nhau tùy từng đối tượng) Qua theo dõi đánh giá thì đa số học sinh đềutiếp thu được và sau khi đã nắm được các kiến thức cơ bản như trong đề tài thìkhi gặp các bài toán hình học khác các em giải quyết các bài toán đó hiệu quảhơn rất nhiều so với trước đó
Vì điều kiện hạn chế về thời gian và khuôn khổ của đề tài nên các bài tập ví
dụ chưa nhiều và cũng chưa bao quát hết các dạng, mặt khác đề tài cũng khôngtránh khỏi hạn chế, thiếu sót nhất định Tôi hy vọng nhận được những góp ýđóng góp của bạn bè đồng nghiệp để đề tài được hoàn thiện hơn, góp phần nhỏcho công tác giảng dạy bồi dưỡng học sinh
Tôi xin chân thành cảm ơn!
XÁC NHẬN CỦA THỦ TRƯỞNG
ĐƠN VỊ Thanh Hóa, ngày 15 tháng 5 năm 2017
Tôi xin cam đoan đây là SKKN của mình viết, không sao chép nội dung của người khác.
Nghiêm Quang Khải