Đối với các bài toán hình học thì tình huống khác hẳn, ngay cả các phép toán sơ cấp trên điểm và đoạn thẳng cũng có thể là một thách thức về tính toán.. Trong các bài toán tin học thuộc
Trang 1PHƯƠNG PHÁP GIẢI TOÁN HÌNH HỌC BẰNG NNLT PASCAL
I KHÁI NIỆM HÌNH HỌC VÀ CÁC ĐỐI TƯỢNG HÌNH HỌC CƠ BẢN
1 Khái niệm hình học
Đa số các thuật toán đều tập trung vào văn bản và các con số, chúng được thiết kế và xử lý sẵn trong phần lớn các môi trường lập trình Đối với các bài toán hình học thì tình huống khác hẳn, ngay cả các phép toán sơ cấp trên điểm và đoạn thẳng cũng có thể là một thách thức về tính toán.
Các bài toán hình học thì dễ hình dung một cách trực quan nhưng chính điều
đó lại có thể là một trở ngại Nhiều bài toán có thể giải quyết ngay lập tức bằng cách nhìn vào một mảnh giấy nhưng lại đòi hỏi những chương trình không đơn giản.
VÝ dô: Bµi to¸n kiÓm tra mét ®iÓm cã n»m trong ®a gi¸c hay kh«ng?
2 Đố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ác định là cặp (x,y) trong hệ toạ độ đề các.
- Đoạn thẳng: Là cặp điểm được nối với nhau bằng một phần của đường thẳng.
- Đa giác: Là dãy các điểm mà 2 điểm liên tiếp nối với nhau bởi đoạn thẳng
và điểm đầu nối với điểm cuối tạo thành đường gấp khúc khép kín.
3 Dữ liệu lưu trữ các đối tượng hình học cơ bản
Type
point = record x,y: integer; end;
Line = record p1,p2: point; end;
Var Polygon: Array[0 Nmax] of Point;
II MỘT SỐ PHÉP TOÁN CƠ BẢN
1 Vị trí tương đối của điểm so với đường thẳng, tia và đoạn thẳng
Bài toán 1: Cho điểm M(x0,y0), A(xA,yA), B(xB,yB) Yêu cầu:
a) Kiểm tra M có thuộc đường thẳng đi qua 2 điểm A, B hay không?
b) Kiểm tra M có thuộc đoạn thẳng AB hay không
c) Kiểm tra M có thuộc tia AB hay không
• Phương pháp:
Đặt F(X,Y) = (yA-yB)X + (xB-xA)Y + (xAyB - xByA)
- Điểm M thuộc đường thẳng AB khi F(x0,y0) = 0
- Điểm M thuộc đoạn thẳng AB khi:
F(x0,y0)=0 và Min(xA,xB) ≤ x0≤ Max(xA,xB) và Min(yA,yB) ≤ y0≤ Max(yA,yB)
Trang 2- Điểm M thuộc tia AB khi F(x0,y0) = 0 và AM = k AB có nghĩa là M phải thoả
mãn điều kiện: F(x0,y0) = 0 và (x0-xA)(xB-xA) ≥ 0 và (y0-yA)(yB-yA) ≥ 0
write('nhap toa do diem A:'); readln(xa,ya);
write('nhap toa do diem B:'); readln(xb,yb);
until (xa<>xb) or (ya<>yb);
write('nhap toa do diem M:'); readln(xo,yo);
if F(xo,yo)=0 then writeln('M thuoc duong thang AB')
else writeln('M ko thuoc duong AB');
if (F(xo,yo)=0) and (min(xa,xb)<=xo) and (xo<=max(xa,xb)) and (min(ya,yb)<=yo) and (yo<=max(ya,yb))
then writeln('M thuoc doan thang AB') else writeln('M khong thuoc doan thang AB');
if (F(xo,yo)=0) and ((xo-xa)*(xb-xa)>=0) and ((yo-ya)*(yb-ya)>=0)
then writeln('M thuoc tia AB') else writeln('M khong thuoc tia AB'); readln;
End
2 Giao của các đoạn thẳng, đường thẳng và tia
Bài toán 2 Cho 2 đường thẳng có phương trình a1x+b1y+c1=0 và a2x+b2y+c2=0 Tìm giao điểm (nếu có) của 2 đường thẳng trên.
• Phương pháp:
B1 Tính D = a1b2 - a2b1, Dx = c2b1 - c1b2, Dy = a2c1 - a1c2
B2 Xét 3 khả năng:
+ Nếu D=Dx=Dy=0 thì kết luận 2 đường thẳng trùng nhau
+ Nếu D=0 và ((Dx ≠ 0) hoặc (Dy ≠ 0)) thì kết luận 2 đường thẳng song song + Nếu D ≠ 0 thì kết luận 2 đường thẳng cắt nhau tại điểm có (Dx/D, Dy/D)
write('nhap he so cua dt 1 a1,b1,c1:'); readln(a1,b1,c1);
write('nhap he so cua dt 2 a2,b2,c2:'); readln(a2,b2,c2);
end;
{=============}
Begin
Trang 3Bài toán 3 Cho 2 đoạn thẳng AB và CD với A(x1,y1), B(x2,y2), C(x3,y3),
D(x4,y4) Tìm giao điểm (nếu có) của 2 đoạn thẳng
• Phương pháp:
B1 Tìm giao điểm M của 2 đường thẳng AB và CD
B2 Kiểm tra M có thuộc đồng thời cả 2 đoạn AB và CD hay không Nếu có đó
là giao điểm cần tìm, ngược lại kết luận không có.
write('nhap toa do diem A:'); readln(xa,ya);
write('nhap toa do diem B:'); readln(xb,yb);
write('nhap toa do diem C:'); readln(xc,yc);
write('nhap toa do diem D:'); readln(xd,yd);
until ((xa<>xb) or (ya<>yb)) and ((xa<>xb) or (ya<>yb));
if (min(xa,xb)<=xo) and (xo<=max(xa,xb))
and (min(ya,yb)<=yo) and (yo<=max(ya,yb))
then Ktra:=true else Ktra:=false;
Bài toán 4 Cho tia AM chứa điểm B (khác A) và đoạn thẳng CD với A(x1,y1),
B(x2,y2), C(x3,y3), D(x4,y4) Tìm giao điểm (nếu có) của tia AM với đoạn thẳng CD.
Trang 4• Phương pháp:
B1 Tìm giao điểm N của 2 đường thẳng AB và CD
B2 Kiểm tra N có thuộc tia AM và đoạn thẳng CD hay không Nếu có đó là giao điểm cần tìm, ngược lại kết luận không có.
write('nhap toa do diem A:'); readln(xa,ya);
write('nhap toa do diem B:'); readln(xb,yb);
write('nhap toa do diem C:'); readln(xc,yc);
write('nhap toa do diem D:'); readln(xd,yd);
until ((xa<>xb) or (ya<>yb)) and ((xa<>xb) or (ya<>yb));
if (min(xa,xb)<=xo) and (xo<=max(xa,xb))
and (min(ya,yb)<=yo) and (yo<=max(ya,yb))
then Ktra:=true else Ktra:=false;
and ((Dx/D-xa)*(xb-xa)>=0) and ((Dy/D-ya)*(yb-ya)>=0)
then writeln('Tia AM cat doan thang CD tai M(',Dx/D:5:2,',',Dy/D:5:2,')') else write('Tia AM khong cat doan thang CD');
3 Vị trí của điểm so với đa giác
Bài toán 5 Cho đa giác gồm N đỉnh d1, d2, ,dN và điểm M Xác định vị trí
tương đối của M với miền trong đa giác.
Phương pháp:
B1 Kiểm tra M có thuộc cạnh nào của đa giác hay không, nếu có thì kết luận
M thuộc miền trong đa giác và kết thúc
B2 Kẻ MN song song với trục hoành (điểm N có hoành độ lớn hơn max hoành
độ của đa giác)
Trang 5B3 Xác định d là số giao điểm của MN với các cạnh của đa giác Những trường hợp sau được coi như là tăng thêm 1 giao điểm:
+ Đỉnh d[i] không thuộc đoạn thẳng MN, đỉnh d[i+1] nằm trên đoạn thẳng
MN, 2 đỉnh d[i] và d[i+2] khác phía so với đường thẳng MN.
+ Đỉnh d[i-1], d[i+2] ngoài đoạn thẳng MN, hai đỉnh d[i] và d[i+1] thuộc đoạn
MN, d[i-1] và d[i+1] khác phía so với đường thẳng MN
+ Đỉnh d[i] và d[i+1] không thuộc MN và cạnh (d[i],d[i+1]) cắt đoạn thẳng MN
III MỘT SỐ DẠNG BÀI TOÁN HÌNH HỌC THƯỜNG GẶP
Dạng 1 Mối quan hệ giữa điểm, đoạn thẳng, đa giác.
Phương pháp: Đây là một trong số dạng bài toán hình học đơn giản nhất
Việc giải bài toán dạng này chủ yếu sử dụng các kiến thức hình học cơ bản (đã trình bày đầy đủ trong phần trên)
- N dòng tiếp theo, mỗi dòng ghi toạ độ của một điểm.
Output: Ghi vào tệp KQ.OuT chứa một số duy nhất là số bộ 3 điểm thẳng hàng.
(Giới hạn: 1<=N<=2000, toạ độ các điểm có giá trị tuyệt đối không quá 10000)
assign(f,'DL.INP'); reset(f); readln(f,n);
for i:=1 to n do readln(f,a[i].x,a[i].y);
Trang 6Dữ liệu: Cho trong file DL.INP gồm N dòng (N không biết trước) Dòng thứ
i ghi 4 số thực xAi yAi xBi yBi Các số trên cùng một
dòng ghi cách nhau ít nhất một dấu cách.
type dthang=record x1,y1,x2,y2:integer; end;
heso=record a,b,c:integer; end;
var pt:array[1 100] of heso;
§/th¼ng 1 c¾t ®/th¼ng 3
§/th¼ng 2 c¾t ®/th¼ng 3
Trang 7{===Tim giao diem===}
VD3 Điểm thuộc đa giác.
Cho đa giác không tự cắt A1A2 AN với các đỉnh Ai(xi,yi) nguyên Với điểm A(xA,yA) cho trước, hãy xác định xem A có nằm trong đa giác đã cho hay không (Trong trường hợp trên cạnh đa giác xem như nằm trong đa giác)
Dữ liệu: Cho trong tệp Dagiac.inp
- Lưu toạ độ các đỉnh đa giác vào mảng A
- Kiểm tra xem điểm A có trùng với đỉnh đa giác
- Kiểm tra xem điểm A có nằm trên cạnh đa giác
- Tìm giao điểm nếu có của tia Ax (Ax//Ox và Ax hướng theo phần dương trục hoành) với các cạnh của đa giác Trường hợp tia Ax chứa đoạn thẳng cạnh đa giác ta xem như tia Ax có 1 điểm chung với cạnh này Cụ thể:
+ Giả sử điểm A(x0,y0), chọn điểm B(xb,yb) với xb=x0+1,yb=y0
+ Kiểm tra tia AB có cắt đoạn thẳng CD bằng cách:
B1 Tìm giao điểm N của 2 đường thẳng AB và CD
10 10
§iÓm A(10,10)kh«ng n»m trong ®a gi¸c
Trang 8- Điểm N thuộc đoạn thẳng CD khi: Min(xC,xD) ≤ xN ≤ Max(xC,xD) và Min(yC,yD) ≤ yN ≤ Max(yC,yD)
- Điểm N thuộc tia AB khi AN = k AB có nghĩa là N phải thoả mãn điều kiện: (xN-xA)(xB-xA) ≥ 0 và (yN-yA)(yB-yA) ≥ 0
+ Kiểm tra tia AB chưa cạnh CD hay không bằng cách: (yc=yd)and(yc=yo)
- Đếm số giao điểm, nếu số giao điểm lẻ thì A thuộc đa giác
if xa>xb then begin Max1:=xa;min1:=xb end else begin Max1:=xb;min1:=xa; end;
if ya>yb then begin Max2:=ya;min2:=yb end else begin Max2:=yb;min2:=ya; end;
if (min1<=xo) and (xo<=max1) and (min2<=yo) and (yo<=max2)
then Ktra:=true else Ktra:=false;
Trang 9if ((D<>0) and (ktrăDx/D,Dy/D,xc,yc,xd,yd)) and ((Dx/D-xa)*(xb-xa)>=0) and ((Dy/D-ya)*(yb-ya)>=0))
if kiemtradinh then exit;
if kiemtracanh then exit;
dem:=0; dem1:=0;
for i:=1 to n do
if kiemtra_giaodiem(A[N+2].x,A[n+2].y,A[i].x,A[i].y,A[i+1].x,A[i+1].y) then Dem:=dem+1;
if dem mod 2=0 then kiemtra:=false;
write('Diem Ắ,a[n+2].x:0:2,',',A[n+2].y:0:2,') nam trong da giac')
else write('Diem Ắ,a[n+2].x:0:2,',',A[n+2].y:0:2,') khong nam trong
da giac');
readln;
end
VD4 Đếm số điểm có toạ độ nguyên thuộc đa giác (Bài đã được đăng trên tạp
chí Tin học & Nhà trường số 04/2009)
Cho đa giác gồm n đỉnh (x1,y1), (x2,y2), ., (xn,yn), biết (2<n<104), xi và yi(i=1, ,n) là các số nguyên trong đoạn [-106,106] Các đỉnh
được liệt kê theo thứ tự cùng chiều kim đồng hồ Viết
chương trình tìm số điểm có toạ độ nguyên nằm trong hay
trên biên đa giác.
Dữ liệu: Cho trong tệp tin DL.INP.
- Dòng đầu chứa số nguyên duy nhất cho biết số đỉnh
- Tiếp theo là các dòng, trên mỗi dòng có 2 số nguyên cách nhau một khoảng trắng lần lượt là hoành độ, tung độ các đỉnh đa giác
Kết quả: Xuất ra màn hình số điểm có toạ độ nguyên nằm trong hay trên biên
đa giác
• Ý tưởng:
- Tính a,b theo công thức:
) )(
( ) )(
y x x
= − −
) ,
( )
y x x UCLN
Trang 10Dạng 2 Tính diện tích đa giác
Phương pháp: Giả sử cho đa giác có n đỉnh và toạ độ các đỉnh lưu vào mảng
a Để tính diện tích đa giác ta làm như sau:
Bước 1 Gắn thêm đỉnh phụ:
a[n+1].x:=a[1].x; a[n+1].y:=a[1].y;
Bước 2 Diện tích đa giác tính theo công thức:
2 / ) ].
[ ].
1 [ )(
].
[ ].
1 [ (
1
y i a y i a x i a x i a
i
+ +
− +
- Nếu đa giác là hình chữ nhật (n=4) có các cạnh là a,b thì diện tích là: S=ab
- Nếu đa giác là hình vuông (n=4) có cạnh là a thì diện tích là: S=a2
- Nếu đa giác là hình tròn có bán kính R thì diện tích là Π R2
VD1 Xác định diện tích đa giác
Cho N đa giác lồi A1A2A3 AN-1AN với các đỉnh Ai(xi,yi) có toạ độ nguyên Hãy tính diện tích đa giác trên.
Dữ liệu: Cho trong file DL.INP gồm 2 dòng
- Dòng 1: Chứa số nguyên dương N
- Dòng 2: Chứa 2xN số nguyên dương x1 y1 x2 y2 xN yN là toạ độ các đỉnh của
đa giác Mỗi số ghi cách nhau một dấu cách.
Kết quả: Xuất ra màn hình diện tích đa giác.
Trang 11- Sử dụng công thức tính diện tích đa giác:
Dữ liệu: Cho trong file HCN.inp gồm N+1 dßng.
0 0 7 7-6 0 0 7
-3 -4 0 -2-6 -2 -3 0-6 -4 0 0-6 0 0 7
0 0 7 7
Trang 12assign(f,'HCN.inp'); reset(f); readln(f,n);
for i:=1 to n do readln(f,a[i].x1,a[i].y1,a[i].x2,a[i].y2);
Bước 2 Sắp xếp mảng a,b theo thứ tự tăng dần
Bớc 3 Lần lượt kiểm tra cỏc hỡnh chữ nhật cú toạ độ đỉnh trờn bờn phải (xi+1,yi+1) và toạ độ đỉnh dưới bờn phải là (xi,yi) với 1 ≤ i ≤ n-1 Nếu hỡnh chữ nhật này thuộc một trong cỏc hỡnh chữ nhật ban đầu thỡ cộng thờm vào phần diện tớch đang cần tỡm diện tớch của hỡnh chữ nhật con này.
VD1 Diện tích phủ bởi các hình chữ nhật (Bài đã đợc đăng trên tạp chí Tin học
& Nhà trờng số 02/2009)
Trong mặt phẳng toạ độ trực chuẩn, cho N hỡnh chữ nhật cú cỏc cạnh song song với trục toạ độ Mỗi HCN được xỏc định bởi toạ độ đỉnh dưới bờn trỏi và đỉnh trờn bờn phải của nú Hóy tớnh diện tớch phần mặt phẳng bị phủ bởi cỏc HCN trờn.
Trang 13Dữ liệu: Cho trong file HCN.inp gồm N+1 dòng.
- Dòng 1: Chứa số N
-Dòng i+1 (1 ≤ i ≤ N): Ghi 4 số nguyên x1,y1,x2,y2 lần lượt là toạ độ đỉnh dưới bên trái và đỉnh trên bên phải của HCN i.
Các số ghi trên một dòng cách nhau ít nhất một dấu cách.
Kết quả: Đưa ra màn hình diện tích phần mặt phẳng bị phủ bởi hình chữ nhật
- Lần lượt kiểm tra các hình chữ nhật có toạ độ đỉnh trên bên phải (xi+1,yi+1)
và toạ độ đỉnh dưới bên phải là (xi,yi) với 1 ≤ i ≤ n-1 Nếu hình chữ nhật này thuộc một trong các hình chữ nhật ban đầu thì cộng thêm vào phần diện tích đang cần tìm diện tích của hình chữ nhật con này.
{===Sap xep mang tang dan===}
Procedure Sapxep(Var T:Mang);
-3 -4 0 -2 -6 -4 0 0 -6 -2 -3 0
0 0 7 7 -6 0 0 7
115
Trang 14if (a[k].x1<=x[i-1]) and (X[i]<=a[k].x2)
and (a[k].y1<=y[j-1]) and(Y[j]<=a[k].y2) then exit;
hình chữ nhật có diện tích nhỏ nhất chứa N hình chữ nhật đã cho.
Dữ liệu vào: Đọc từ tệp PHUCN.INP có cấu trúc:
- Dòng đầu tiên chứa N (N ≤ 30);
- Trong N dòng tiếp theo, mỗi dòng ghi 4 số là toạ độ của hai đỉnh đối tâm của một hình chữ nhật, các số này là các số nguyên có trị tuyệt đối không quá 100.
Kết quả: Ghi ra tệp văn bản PHUCN.OUT
- Dòng 1 ghi toạ độ hai đỉnh đối tâm của phủ S các hình chữ nhật
- Dòng 2 ghi diện tích của phần hình S không nằm trong hình chữ nhật nào trong N hình đã cho
• Ý tưởng:
- Xác định hình chữ nhật H nhỏ nhất bao tất cả các hình chữ nhật ban đầu: Gọi minx,maxx lần lượt là hoành độ nhỏ nhất và lớn nhất trong các hoành độ các đỉnh hình chữ nhật đã cho; miny, maxy lần lượt là tung độ nhỏ nhất và lớn nhất trong các tung độ các đỉnh hình chữ nhật đã cho Khi đó hình H có toạ độ đỉnh dưới trái là (minx,miny) và đỉnh trên phải là (max,maxy) Đó là phủ S cần tìm.
Trang 15if a[i].x1<minx then minx:=a[i].x1;
if a[i].x2<minx then minx:=a[i].x2;
if a[i].y1<miny then miny:=a[i].y1;
if a[i].y2<miny then miny:=a[i].y2;
if a[i].x1>maxx then maxx:=a[i].x1;
if a[i].x2>maxx then maxx:=a[i].x2;
if a[i].y1>maxy then maxy:=a[i].y1;
if a[i].y2>maxy then maxy:=a[i].y2;
end;
close(f);
end;
{=================Sap xep mang tang dan=========}
Procedure sapxep(var t:mang);
if (a[k].x1<=x[i-1]) and (x[i]<=a[k].x2)
and (a[k].y1<=y[j-1]) and (y[j]<=a[k].y2) then exit;
Trang 16Dữ liệu: Cho trong file INP.BL3 dòng đầu là số lượng hình tròn, từ dòng thứ
2 trở đi mỗi dòng chứa 3 số nguyên dương là tọa độ x, y của tâm và bán kính của từng hình tròn (các số trên cùng một dòng ghi cách nhau ít nhất 1 dấu cách)
• Chương trình
program Hinh_tron;
type DT=record x,y,r:longint end;
var a:array[1 100] of DT; s:real;
Trang 17Dạng 4 Xác định đa giác nhỏ nhất bao tất cả các điểm, đa giác đã cho
Phương pháp: Cho N điểm A1, A2, , AN trên mặt phẳng Để xác định một đa giác không tự cắt chứa một số điểm đã cho và bao tất cả các điểm còn lại ta làm như sau:
Bước 1 Tìm điểm có tung độ nhỏ nhất Điểm đó sẽ là đỉnh đa giác
Bước 2 Giả sử ta đã chọn được điểm PM Tìm điểm Pi sao cho góc hợp bởi
PMPi và trục hoành là nhỏ nhất và đồng thời góc này phải lớn hơn góc hợp bởi PMP
M-1 và trục hoành Điểm Pi sẽ là một đỉnh của đa giác.
Bước 3 Lấy kết quả là dãy các đỉnh P tìm được.
Lưu ý: Với bài toán tìm đa giác bao nhau thì cần ghi nhớ đa giác a bao đa giác b khi mọi điểm trong đa giác b đều nằm trong đa giác a.
VD1 Đa giác không tự cắt
Cho N điểm A1, A2, , AN trên mặt phẳng Các điểm đều có toạ độ nguyên
và không có 3 điểm bất kỳ trong chúng thẳng hàng Hãy viết chương trình thực hiện các công việc sau đây: Xác định một đa giác không tự cắt có đỉnh là một số điểm trong các điểm đã cho và chứa tất cả các điểm còn
lại và có chu vi nhỏ nhất Hãy tính diện tích đa giác này.
Dữ liệu: cho trong tệp HCN.INP gồm n+1 dòng
+ Dòng 1: Chứa số N
+ Dòng i+1 (1 ≤ i ≤ N): Ghi 2 chữ số nguyên xi,yi là toạ độ đỉnh Ai
Các số trên cùng một dòng cách nhau một khoảng trắng.
Kết quả: Xuất ra tệp HCN.Out
+ Dòng 1: Ghi 3 số K, V, S với K là số đỉnh đa giác tìm được, V là chu vi, S