Tải bản đầy đủ (.pdf) (33 trang)

CHUYÊN đề bồi DƯỠNG học SINH GIỎI môn TIN học CHUYÊN đề HÌNH học

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.54 MB, 33 trang )

CHUYÊN ĐỀ BỒI DƯỠNG HỌC SINH GIỎI MÔN TIN HỌC
CHUYÊN ĐỀ HÌNH HỌC
MÃ: TI08
Để đáp ứng được yêu cầu của công tác giảng dạy đội tuyển Tin học. Bản thân
mỗi giáo viên chúng ta luôn phải tìm tòi, nghiên cứu, trao đổi kiến thức và kinh
nghiệm giảng dạy với các đồng nghiệp. Bên cạnh đó, nguồn tài liệu trên mạng cũng
là một nguồn quý giá đối với giáo viên chúng ta. Tuy nhiên, việc tổng hợp, biên tập
thành tài liệu có nội dung phù hợp cho đối tượng học sinh của mình lại là một vấn đề
quan trọng hơn nữa.
Vì vậy, với chuyên đề này tôi xin được đề cập đến một tài liệu được sưu tầm
mà tôi thường dùng để giảng dạy cho học sinh trong đội tuyển, những bài toán mà
bản thân tôi thấy tâm đắc. Nguồn đề và bài giải trong chuyên đề này được tôi sưu tầm
từ: spoj, laptrinh.ntu, kienthuc24h.
Tài liệu này bố cục thành hai phần:
• Kiến thức hình học cơ bản
• Hệ thống bài tập quan trọng về hình học


A. KIẾN THỨC HÌNH HỌC CƠ BẢN
I. Tọa độ
1. Hệ trục toạ độ oxy gồm ba trục ox, oy đôi một vuông góc với nhau với ba vectơ
r ur

đơn vị i , j

r

r

( i = j = 1).


uur

ur

2. a ( a1; a2 ) ⇔ a

ur
uur
= a1i + a2 j ;

uuuuur

ur

uur

M(x;y)⇔ OM = xi + y j
r

r

3. Tọa độ của vectơ: cho u( x; y), v( x '; y ')
r

r

a. u = v ⇔ x = x '; y = y '
ur r

d. u.v = xx '+ yy '

g.

r

r

r

e. u ⊥ v ⇔ xx '+ yy ' = 0

ur r
u.v
r r
cos u, v = r r

( )

r

b. u ± v = ( x ± x '; y ± y ')

u.v

r

c. ku = (kx; ky)
r

f. u = x 2 + y 2


.

4. Tọa độ của điểm: cho A(xa;ya), b(xb;yb)
uuur

a. AB = ( xB

b. AB = ( xB − x A )2 + ( yB − y A )2

− x A ; yB − y A )

c. G là trọng tâm tam giác ABC ta có:
xG =

x A + xB + xC
3

; yG =

y A + yB + yC
3

d. M chia AB theo tỉ số k: xM =

x A − kxB
y − kyB
; yM = A
1− k
1− k


Đặc biệt: M là trung điểm của AB: xM =

x A + xB
y + yB
; yM = A
.
2
2

II. Phương trình đường thẳng
1. Một đường thẳng Δ được xác định khi biết một điểm M(x0;y0) và một vectơ pháp
r

r

tuyến n = ( A; B ) hoặc một vectơ chỉ phương a = ( a; b )
Phương trình tổng quát A ( x − x0 ) + ( y − y0 ) = 0 ⇔ Ax + By + C = 0 .
⎧ x = x0 + at
, (t ∈ R ) .
⎩ y = y0 + bt

Phương trình tham số: ⎨

n
a

Phương trình đường thẳng qua M có hệ số góc k:
y = k ( x − x0 ) + y0 .

2. Khoảng cách từ một điểm M(xM;yM) đến một đường thẳng Δ:


Δ

Ax + By + C = 0 là:

d (M , Δ) =

AxM + ByM + C
A2 + B 2

.
Δ

III. Phương trình đường tròn
1. Một đường tròn được xác định khi biết tâm I(a;b) và bán kính r.
Phương trình:

r
M
I

(C)


Dạng 1: ( x − a )2 + ( y − b )2 = r 2 .
Dạng 2: x2 + y 2 − 2ax − 2by + d = 0 , điều kiện a 2 + b2 − d > 0 và r = a 2 + b2 − d .
2. Điều kiện để đường thẳng Δ: Ax + By + C = 0 tiếp xúc với đường tròn (C) là:
d ( I , Δ) =

Aa + Ba + C

A2 + B 2

=r

IV. Hình học phẳng
1. Các công thức tính diện tích tam giác
- Dùng hình học
Diện tích S bằng S = ½bh, trong đó b là độ dài của một cạnh bất kỳ của tam giác
(thường gọi là đáy) và h là độ dài đường cao hạ từ đỉnh đối diện xuống cạnh ấy.
Có thể giải thích công thức này bằng cách dùng diện tích hình chữ nhật như sau:

Diện tích tam giác bằng một nửa diện tích hình bình hành, diện tích hình bình hành
bằng diện tích một hình chữ nhật.
Từ một tam giác (màu xanh lá cây), ta sao một tam giác bằng nó,(màu xanh lam),
quay góc 180°, và ghép chúng thành hình bình hành. Cắt một phần của hình bình
hành, ghép lại thành hình chữ nhật. Vì diện tích hình chữ nhật là bh, nên diện tích
tam giác là ½bh.
Nói cách khác, diện tích tam giác bằng độ dài cạnh đáy nhân với chiều cao chia 2:
- Dùng vectơ

Diện tích hình bình hành là tích có hướng của hai vectơ.
Nếu tứ giác ABDC là hình bình hành thì diện tích của nó được tính bởi công thức:

trong đó

là tích có hướng của hai vectơ



.


Diện tích tam giác ABC bằng một nửa diện tích của hình bình hành ABDC nên:


- Dùng lượng giác

Sử dụng lượng giác để tính diện tích tam giác.




nên ta có:

- Dùng tọa độ
Nếu đỉnh A đặt ở gốc tọa độ (0, 0) của hệ tọa độ Descartes và tọa độ của hai đỉnh kia
là B = (xB, yB) và C = (xC, yC), thì diện tích S của tam giác ABC bằng một nửa của giá
trị tuyệt đối của định thức

Trong trường hợp tổng quát, ta có:

Trong không gian ba chiều, diện tích của tam giác cho bởi {A = (xA, yA, zA),
B = (xB, yB, zB) và C = (xC, yC, zC)} là tổng 'Pythagor' của các diện tích các hình chiếu
của chúng trên các mặt phẳng tọa độ (nghĩa là x=0, y=0 and z=0):

- Dùng công thức Heron
Cũng có thể tính diện tích tam giác S theo Công thức Heron:

trong đó
V. Đa giác lồi


là nửa chu vi của tam giác.


1. Số đường chéo trong một đa giác lồi có N đỉnh:

!(!!!)
!

2. Cho n điểm đôi một phân biệt trên mặt phẳng (n ≥ 3). Có n(n-1)(n-2)/6 tam giác có

các đỉnh là 3 đỉnh phân biệt trong số n điểm này (bao gồm cả những tam giác bị suy
biến, nghĩa là khi cả 3 đỉnh thẳng hàng).
3. Tổng khoảng cách từ 1 điểm trong tứ giác đến các đỉnh bé nhất bằng tổng hai
đường chéo.
4. Chứng minh rằng qua điểm (a, b) có thể dựng được một đường thẳng cắt góc tọa
độ thứ nhất tạo thành một tam giác vuông, sao cho trong hoặc trên cạnh của tam giác
này có tất cả là 2ab+a+b+1 điểm với tọa độ nguyên.
5. công thức tính diện tích đa giác lồi theo tọa độ
S = |∑(xⁿ+¹ - xⁿ)(yⁿ+¹ + yⁿ)/2|
Hoặc: S = |∑(xⁿ+¹ + xⁿ)(yⁿ+¹ - yⁿ)/2|
Trong đó n chạy từ 1 đến số đỉnh của đa giác, đỉnh thứ n+1 coi là đỉnh 1

đỉnh

là:

VI. Điểm, đường thẳng, đoạn thẳng
a. Điểm (Point):
Trong hình học, chúng ta xét trong hệ Đề các xoy, thì một điểm có toạ độ: (x,y).
Chính vì thế ta lưu tọa độ một điểm trong một bản ghi Record:

Type
point = Record
x , y : integer ;
End ;
vì vậy khi xét tới toạ độ của P(x,y) thì ta xét P.x, P.y
Chúng ta biết khoảng cách giữa hai điểm P(x1,y1)và Q(x2,y2) trong mặt phẳng:
Function Khoang_Cach(P,Q: Point_Chung ) : Real ;
Begin
Khoang_Cach:=Sqrt(Sqr(P.x-Q.x)+Sqr(P.y-Q.y));
End ;
b. Đường thẳng (line):
Trong hình học, chúng ta có phương trình của một đường thẳng trong mặt phẳng:
Ax+By+C =0. Chúng ta coi A, B, C là biểu diễn cho đường thẳng đó. Nếu một đường
thẳng (d):
Ax + By + C = 0, đi qua 2 điểm A (x1,y1) và B(x2,y2) thì nó có:
A:= y1- y2;
B:= x2 – x1;


C:= -(A.x1+B.y1).
Chính vì thế chúng ta dùng thủ tục xác định A, B, C của một đường thẳng đi qua 2
điểm như sau:
Procedure Xac_DinhABC(P, Q: Point, var A , B , C: Longint );
Begin
A := P.y-Q.y ;
B := Q.x-P.x ;
C := -(A*P.x+B*P.y ) ;
End ;

Và chúng ta có thể coi đường thẳng là một kiểu:

Type
Lines = Record
a , b , c : Longint;
End ;

c. Đoạn thẳng:
Đoạn thẳng là một phần của đường thẳng, bị giới hạn x, y. Chúng ta xét đoạn thẳng
thông thường cho đi qua 2 điểm. Chính vì thế toạ độ x, y bị giới hạn trong khoảng đó.
2. Phương trình tương quan giữa điểm và đường thẳng, đoạn thẳng:
a. Tương quan giữa điểm và đường thẳng:
Cho đường thẳng (d) có phương trình: Ax +By + C = 0 và P(x,y).
Thì phương trình:
F(x,y) = A*P.x + B*P.y + C, là phương trình tương quan của P với (d). Đúng vậy:
* Nếu F (x,y)=0 thì P thuộc (d). Ngược lại nếu F(x,y)<>0 thì P không thuộc (d).
* Nếu Q (x1,y1) mà nằm cùng phía không thuộc (d) thì F (x1,y1)*F(x,y)>0, và nếu
khác phía thì F(x1,y1)*F(x,y)<0. Đây là một trong những điều kiện giúp ích cho ta
rất nhiều trong giải toán tin hình học và cũng là một phương tiện thiết kế chương
trình trong hình học dẽ dàng hơn.
Chúng ta xây dựng hàm Phuong_Trinh để xác định mối tương quan của đường thẳng
với một điểm:
Function Phuong_trinh (L : Lines ; P : Point_Chung ) : Real ;
Begin
Phuong_Trinh:=L.a*P.x+L.b*P.y+L.c;
End ;

b. Tương quan của điểm với đoạn thẳng.
Chúng ta biết rằng, đoạn thẳng là một phần đường thẳng. Nên mối tương quan giữa
điểm P(x,y) với đoạn thẳng AB, (A (x1,y1), B(x2,y2)) là:
– Nếu P[AB] thì:



+ F(x,y)=0, tức là: a*x+b*y+c=0, với a=y1-y2; b=x2-x1 và c=- (a*x1+b*y1).
+ (x-x1)*(x-x2)<=0 và (y-y1)*(y-y2)<=0.
– Nếu P[AB] thì:
+ Nếu F(x,y)=0 thì: (x-x1)*(x-x2)>0 hoặc (y-y1)*(y-y2)>0.
+ Nếu F(x,y)<>0 thì P không thuộc đường thẳng qua A, B.
Ta có thể xây dựng hàm kiểm tra 1 điểm P có thuộc đoạn AB như sau:
Function thuoc_doan ( P : Point_Chung ; A, B : Point ) : Boolean ;
Var a , b , c : longint ; t : Real ;
Begin
xac_dinhABC (A, B ,a,b,c) ;
thuoc_doan:=false ;
t := a * P.x + b*P.y + c ;
if t<>0 then exit ;
if ( (P.x-A.x)*(P.x-B.x)>0)
r((P.y-A.y) * (P.y-B.y)>0)
then
Exit ;
thuoc_doan:=True;
End ;

3. Cắt nhau:
a. Đường thẳng cắt đường thẳng:
(1): A1*x+B1*y+C1=0 và (2): A2*x+B2*y+C2=0. Thì ta gọi mối tương quan giữa
(1)và (2) được biểu diễn qua hệ phương trình sau:
A1*x+B1*y=-C1
A2*x+B2*y=-C2
đặt: D=A1*B2-A2*B1;
Dx=B1*C2 – B2*C1;
Dy=C1*B2-A1*C2

* Hai đường thẳng cắt nhau khi và chỉ khi: D≠0. Toạ độ điểm giao của hai đường
thẳng này là: x=Dx/D, y= Dy/D
* Hai đường thẳng song song với nhau khi và chỉ khi: D=0 và Dx ≠ 0 hoặc Dy ≠ 0.
* Hai đường thẳng trùng nhau khi: D=Dx=Dy=0.
Chúng ta có thể xây dựng hàm kiểm tra cắt nhau của hai đường thẳng.
Hàm Lines_Cut có giá trị:
1: Nếu hai đường thẳng đó cắt nhau
2: Nếu hai đường thẳng đó song song nhau
3: Nếu hai đường thẳng đó trùng nhau.
Function Lines_cut ( L1 , L2 : Lines ) : Byte ;


var D, Dx,Dy : Longint ;
Begin
D := L1.a*L2.b -L2.a*L1.b;
Dx :=L1.b*L2.c-L1.c*L2.B ;
Dy:=L1.c*L2.b-L1.b*L2.c ;
If D<>0 then Lines_cut:=1
else If D=0 then
Begin
If (Dx<>0)Or(Dy<>0)Then
Lines_cut:=2 ;
If (Dx=0)And(Dy=0)
ThenLines_Cut:=3;
End ;
End ;

b. Đường thẳng cắt đoạn thẳng:
(1): A1*x+B1*y+C1=0 và đoạn AB, A (x1,y1), B(x2,y2).
Đặt A2:=y1-y2; B2:=x2-x1;

C2:=-(A2*x1+B2*y)
D=A1*B2-A2*B1; Dx=B1*C2 -B2*C1; Dy=C1*B2-A1*C2
Mối quan hệ giữa (1) và AB được thể hiện:
* Nếu D ≠ 0 và điểm P(Dx/D,Dy/D) nằm trên đoạn AB thì (1) cắt AB.
* Nếu D ≠ 0 và điểm P(Dx/D,Dy/D) nằm ngoài đoạn AB thì (1) cắt đường thẳng
chứa AB nhưng không cắt AB.
* Nếu D=Dx=Dy=0 thì AB(1).
* Nếu D=0, Dx/D0 hoặc Dy/D0 thì AB song song với (1).
Chúng ta xây dựng hàm: Lines_Cut_AB
Lines_Cut_AB bằng:
1: Nếu đoạn thẳng cắt đường thẳng.
2: Nếu đoạn thẳng song song với đường thẳng
3: Nếu đoạn thẳng thuộc đường thẳng.
4: Nếu đường thẳng chứa đoạn thẳng cắt đường thẳng một điểm nằm ngoài đường
thẳng.
Function Lines_Cut_AB (L1:Lines ; P,Q : Point ): Byte;
Var L2 : Lines;
Giao : Point_Chung ;
D , Dx , Dy : Longint ;
Begin
With L2 do Xac_DinhABC (P,Q,a,b,c);
D := L1.a*L2.b -L2.a*L1.b;


Dx :=L1.b*L2.c-L1.c*L2.B ;
Dy:=L1.c*L2.b-L1.b*L2.c ;
If D=0 Then
Begin If (Dx=0)And (Dy=0)Then Lines_Cut_AB:=3;
If ( Dx<>0)Or(Dy<>0)Then Lines_Cut_AB:=2 ;
End ;

If D<>0 Then
Begin
Giao.x := Dx/D ;
Giao.y := Dy/D ;
If Thuoc_Doan (Giao,P,Q) then
Lines_Cut_AB:=1
Else Lines_Cut_AB:=4 ;
End ;
End ;

c. Đoạn thẳng cắt đoạn thẳng:
Xét hai đoạn thẳng AB và CD thì chúng cắt nhau hay không thì chúng ta có thể xét
theo hai cách. Trong bài này tôi xin đề nghị cả hai cách, mỗi cách có những ưu,
nhược điểm khác nhau.
Cách 1:
Cách Theo Phương Trình Đường Thẳng:
Function Cat_Nhau1 (P,Q,M,N: Point) : Boolean ;
Var L : Lines ;
Begin
Cat_Nhau1:=False;
With L Do
Xac_DinhABC(P,Q,a,b,c);
If Lines_Cut_AB(L,M,N)<>1 then Exit;
With L Do
Xac_DinhABC(M,N,a,b,c);
If Lines_Cut_AB(L,P,Q)<>1 then Exit ;
Cat_Nhau1:=True ;
End ;
Cách 2:
(Tham khảo sách Cẩm nang thuật toán - tập 2)

Function ccw ( P0 , p1 , p2 : Point ) : Integer ;
Var Dx1,Dx2,Dy1,Dy2: Integer ;
Begin
Dx1 := P1. x -P0.x ;


Dy1 :=P1.y-P0.y ;
Dx2 := P2. x -P0.x ;
y2 :=P2.y-P0.y ;
If Dx1*Dy2>Dy1*Dx2 then
ccw :=1 ;
If Dx1*Dy2
ccw := -1 ;
If Dx1*Dy2=Dx2*Dy1 then
Begin
If (Dx1*Dx2<0) Or (Dy1*Dy2<0)
Then ccw:=-1
Else If (Dx1*Dx1+Dy1*Dy1) >= (Dx2*Dx2+Dy2*Dy2) then
ccw:=0
else ccw:=1 ;
End ;
End ;
Function Cat_Nhau2(P,Q,M,N : Point) : Boolean ;
Begin
Cat_Nhau2:=((ccw(P,Q,M)*ccw(P,Q,N))<=0)And ((ccw(M,N,P)*ccw(M,N,Q))<=0)
End ;

4. Đa giác:
a. Tam giác:
Một tam giác được định nghĩa là tập ba điểm không thẳng hàng: A (x1,y1); B(x2,y2);

C(x3,y3).
Chúng ta có thể tính diện tích tam giác theo công thức tính diện tích đa giác (công
thức hình thang hoặc công thức Pic mà tôi sẽ bàn sau). Hoặc chúng ta tính theo công
thức Herong:
S:=Sqrt((p-a)*(p-b)*(p-c)*p);
Trong đó a, b, c là độ dài ba cạnh của tam giác. P=(a+b+c)/2;
b. Hình chữ nhật: (trường hợp cho cách cạnh song song các trục toạ độ).
Chúng ta xét trong hệ tọa độ một hình chữ nhật ABCD, A (x1,y1); B(x2,y2);
C(x3,y3); D (x4,y4).
Nhưng có một điều đặc biệt là chúng ta chỉ cần xác định toạ độ đỉnh của hai đỉnh đối
nhau thì xác định đợc một hình chữ nhật duy nhất. Chính vì thế thông thường chúng
ta gọi toạ độ của điểm dưới trái và đỉnh trên phải là hai điểm đặc trưng cho hình chữ
nhật đó.
c. Hình đa giác:
Một đa giác A1A2…An có toạ độ: Ai (xi ,yi).


* Người ta định nghĩa đa giác đó là lồi khi mọi điểm còn lại của đa giác nằm cùng
phía với nhau so với một cạnh nào đó.
* Diện tích một đa giác được tính theo công thức hình thang như sau:
S : = |[(Xi-Xi+1)*(Yi+Yi+1)/2]|
d. Bao lồi:
Bao lồi của một tập điểm là một hình đa giác khép kín có các đỉnh là một trong các
đỉnh của tập điểm đó, và thoả mãn đa giác lồi. Thông thường chúng ta cần phải tìm
đa giác bao với chu vi nhỏ nhất. Có nhiều thuật toán để giải quyết bài toán này. Đặc
biệt phương pháp quét:
Phương pháp quét đường thẳng:
Chúng ta đi từ một đỉnh chắc chắn thuộc bao lồi (là những điểm có tung độ hoành độ
lớn nhất hoặc nhỏ nhất). Chúng ta tìm các đỉnh tiếp theo, đỉnh nào thoả mãn chứa
toàn bộ các đỉnh còn lại một bên mặt phẳng thì ta lấy điểm đó cho đến khi lặp lại

điểm ban đầu.
Procedure Scan;
Begin
Xác định thuộc đa giác ;
Repeat
tìm đỉnh tiêp theo mà thoả mãn điều kiện lồi của đa giác ;
Until lặp lại đỉnh ban đầu ;
End ;
Nội dung về bao lồi là phức tạp tôi xin đề cập vào dịp khác.
Với hệ thống kiến thức cơ sở như trên, đây sẽ là cẩm nang hữu ích cho học
sinh khi làm bài tập về chuyên đề hình học. Phần nội dung này, tôi thường tạo thành
ebook và giao cho học sinh tự nghiên cứu và sử dụng trong quá trình làm bài.


B. HỆ THỐNG BÀI TẬP QUAN TRỌNG VỀ HÌNH HỌC
B1. Mức cơ bản
Nội dung bài tập ở mức này giúp học sinh làm quen với các bài tập về hình học
và sử dụng ebook để tra cứu công thức cũng như tính chất của các hình. Nguồn bài
tập và lời giải do tôi code, sưu tầm trên spoj và kienthuc24h.
1. Tam giác vuông – PTIT138A
Chúng ta đều biết định lý Pitago nổi tiếng về tam giác vuông. Bài toán đặt ra là
cho trước độ dài 3 cạnh của một tam giác. Hãy xác định xem đó có phải tam giác
vuông hay không?
Input
Gồm nhiều bộ test. Mỗi bộ test viết trên một dòng 3 số nguyên dương không quá
30000, lần lượt là độ dài ba cạnh của tam giác.
Input kết thúc với 3 số 0
Output
Với mỗi bộ test, in ra màn hình, trên một dòng, chữ “right” nếu đó là một tam giác
vuông, “wrong” nếu ngược lại.

Example
Input:
6 8 10
25 52 60
5 12 13
000
Output:
right
wrong
right
Const
fi='';
fo='';
function check(x,y,z: longint):boolean;
begin
x:=sqr(x); y:=sqr(y); z:=sqr(z);
exit( (x+y=z) or (z+y=x) or (z+x=y));
end;
Procedure xuli(ii:longint;s1: string);
var j,a,b,k: longint;
begin
end;

Procedure doctep;
var c1,c2,c3: longint;
begin
assign(input,fi);
reset(input);
readln(c1,c2,c3);
assign(output,fo);

rewrite(output);
while (c1>0) and (c2>0 ) and (c3>0) do
begin
if check(c1,c2,c3) then writeln('right')
else writeln('wrong');
readln(c1,c2,c3);
end;
close(input);
close(output);
end;
begin
doctep;
end.


2. Điểm còn lại của hình chữ nhật - PTIT124H
Cho một hình chữ nhật có cạnh song song với các trục. Biết tọa độ 3 đỉnh. Hãy
tìm tọa độ của điểm còn lại của hình chữ nhật.
Input
Gồm 3 dòng: Mỗi điểm trên một dòng chứa tạo độ của điểm đó.
Output
In ra điểm còn lại của hình chữ nhật
Example
Input:
55
57
75
Output:
77
Const

fi='';
fo='';
type diem=record
x,y:longint;
end;
Var
a:array[1..3] of diem;
rx,ry: longint;
Procedure doctep;
var
i:longint;
begin
assign(input,fi);
reset(input);
for i:=1 to 3 do
with a[i] do readln(x,y);
close(input);
end;
Procedure xuli;
var i,j: longint;
tam:diem;
begin
for i:=1 to 2 do
for j:=i+1 to 3 do
if a[i].x>a[j].x then
begin
tam:=a[i];
a[i]:=a[j];

if (a[1].y>a[2].y) then

begin
rx:=a[1].x;
ry:=a[2].y;
exit;
end;
if (a[1].y=a[2].y) then
begin
rx:=a[1].x;
ry:=a[3].y;
exit;
end;
if (a[3].ybegin
rx:=a[3].x;
ry:=a[2].y;
exit;
end;
if (a[2].y=a[3].y) then
begin
rx:=a[3].x;
ry:=a[1].y;
exit;
end;
End;
Procedure ghikq;
begin
assign(output,fo);
rewrite(output);
write(rx,#32,ry);



a[j]:=tam;
end;
for i:=1 to 2 do
for j:=i+1 to 3 do
if (a[i].y>a[j].y) and (a[i].x=a[j].x) then
begin
tam:=a[i];
a[i]:=a[j];
a[j]:=tam;
end;

close(output);
end;
begin
doctep;
xuli;
ghikq;
end.

3. Giao điểm của đường chéo trong đa giác - NUMPOLY
Cho trước một đa giác lồi N cạnh, thỏa mãn không có 3
đường chéo nào đồng quy. Hãy đếm số giao điểm tạo
bởi các cặp đường chéo trong đa giác.
Hình vẽ minh họa với lục giác:
Input
Chứa 1 số nguyên N (3 <= N <=100) duy nhất là số đỉnh
của đa giác.
Output
Số giao điểm tạo bởi các đường chéo nằm trong đa giác.

Example
Input1
3
output
0
Input2
4
output
1
Input3
6
output
15
#include <iostream>
int main(void)
{
int n;
std::cin >> n;
std::cout << n*(n-1)*(n-2)*(n-3)/24;
return 0;
}


4. Khoảng cách - PTIT013C
Với hai điểm P(xP,yP) và Q(xQ,yQ) trên mặt phẳng, khoảng cách giữa chúng được
tính theo công thức:
d(P,Q) = √(xP-xQ)2+(yP-yQ)2.
Nhiệm vụ của bạn là viết chương trình nhập vào 4 số nguyên là tọa độ 2 điểm A,B:
xA, yA, xB, yB và tìm điểm M trên trục Ox để giá trị d(M,A) + d(M,B) đạt giá trị
nhỏ nhất.

Input
Dữ liệu vào gồm nhiều bộ dữ liệu tương ứng với nhiều test. Dòng đầu tiên chứa một
số nguyên dương không lớn hơn 20 là số lượng các bộ dữ liệu. Các dòng tiếp theo
chứa các bộ dữ liệu.
Mỗi bộ test gồm 4 số nguyên xA, yA, xB, yB (có giá trị tuyệt đối < 106).
Output
Với mỗi bộ test, in ra đáp số là phần nguyên của giá trị nhỏ nhất của d(M,A) +
d(M,B).
Example
Input:
1
0121
Output:
2
Nhận xét: 2 điểm A và B nằm cùng phía hay khác phía của Ox thì cũng cho ra giá trị
d(M,A) + d(M,B) là như nhau. nên ta dồn 2 điểm về cùng phía cho dễ tính toán (ta
dùng hàm abs trong bài code mẫu pascal). kẻ B’B với B’ là điểm đối xứng của B qua
Ox, kẻ B’A, giao điểm của B’A và Ox chính là tọa độ tối ưu của M. như vậy ta chỉ
cần tính chiều dài của B’A bằng pytago là được
const fi='';
type data=longint;
var
f:text;
xa,xb,ya,yb,dxa:int64;
i,test:data;
res:int64;
begin
assign(f,fi); reset(f);
readln(f,test);
for i:=1 to test do

begin
readln(f,xa,ya,xb,yb);
writeln(trunc(sqrt( sqr(xa-xb)+sqr(-abs(ya)-abs(yb)) ) ) );


end;
close(f);
end.

5. XOAYDT - Xoay đường tròn (Codeforce 287B)
Cho một đường tròn có bán kính r, tâm đường tròn đang ở tại tọa độ (x, y).
Người ta cần di chuyển tâm đường tròn đến tọa độ (xd, yd) bằng nhiều bước xoay
đường tròn. Tại mỗi bước lấy một cây kim chấm vào một vị trí nào đó trên đường
tròn và xoay tâm đường tròn quanh cây kim này. Hỏi số lần xoay ít nhất là bao
nhiêu?
Dữ liệu nhập:
- Gồm 5 số r, x, y, xd, yd mỗi số cách nhau một khoảng trắng (1  ≤  r  ≤  105,     105  ≤  x,  y,  xd,  yd  ≤  105)
Dữ liệu xuất:
- Là số lần xoay đường tròn ít nhất
Ví dụ
input
20004
output
1
input
11144
output
3
input
45656

output
0
#include <bits/stdc++.h>
#define maxn 105
#define M 1000000000
using namespace std;
long long x, y, a, b, r;
int main()
{
//freopen("int.txt", "r", stdin);
cin >>r >> x >> y >> a >> b;
double aa = sqrt((x- a)*(x-a) + (y -b)*(y- b));
double pp = aa /(2*r);
if (pp - (int)pp) cout << (int)pp +1;
else cout << pp;
}

6. HIVU - Hình vuông
Cho 4 điểm tọa độ nguyên trên mặt tọa độ Decartes. Hỏi 4 điểm đó có tạo
thành một hình vuông hay không?


Dữ liệu nhập: Gồm 4 dòng
- Dòng thứ i gồm hai số nguyên xi và yi là hoành độ và tung độ của điểm thứ i, hai số
cách nhau một khoảng trắng (-100 ≤ xi, yi ≤ 100). Dữ liệu cho đảm bảo không có hai
điểm nào trùng nhau.
Dữ liệu xuất:
- Nếu 4 điểm trên tạo thành một hình vuông, in ra "YES", nếu không phải in ra "NO".
Ví dụ
input

00
10
01
11
output
YES
input
00
01
02
03
output
NO
input
10
12
21
01
output
YES
Hình vuông là hình thoi có hai đường chéo bằng nhau.
#include <bits/stdc++.h>
using namespace std;
pair <int,int> a[5];
vector <int> dist;
main()
{
for (int i=1; i<=4; i++) scanf("%d %d", &a[i].first, &a[i].second);
for (int i=1; i<=3; i++)
for (int j=i+1; j<=4; j++)

dist.push_back((a[i].first-a[j].first)*(a[i].first-a[j].first) + (a[i].second-a[j].second)*(a[i].second-a[j].second));
sort(dist.begin(), dist.end());
printf("%s", (dist[0]==dist[3] && dist[4]==dist[5]) ? "YES" : "NO");
}

7. GHVU - Ghép hình vuông


Ba bé Bo mua cho bé Bo 03 miếng ghép đồ chơi hình chữ nhật và hỏi bé Bo có
ghép 03 hình chữ nhật trên thành một hình vuông lớn được hay không. Bé Bo đang
loay hoay tìm cách ghép. Bạn hãy giúp bé Bo tìm cách ghép để ba tiếp tục mua đồ
chơi cho bé nhé.
Dữ liệu nhập: gồm 3 dòng
- Tại dòng thứ i gồm hai số nguyên ai, bi là chiều dài và chiều rộng của hình chữ nhật
thứ i. (1 ≤ ai, bi ≤ 10). Hai số cách nhau một khoảng trắng.
Dữ liệu xuất:
- Nếu có cách ghép thành hình vuông được, in ra "YES", nếu không, in ra "NO". Chú
ý các hình chữ nhật phải ghép vừa khớp, hình này không đè lên hình kia.
Ví dụ
input
16
26
36
output
YES
input
26
24
44
output

YES
input
22
11
33
output
NO
#include <bits/stdc++.h>
using namespace std;
struct dk
{
int x, y;
} rect[4];
bool cmp(dk X, dk Y)
{
return (X.x != Y.x) ? (X.x < Y.x) : (X.y < Y.y);
}
main()
{
for(int i=1; i<=3; i++)
{
scanf("%d %d", &rect[i].x, &rect[i].y);
if (rect[i].x < rect[i].y)
swap(rect[i].x, rect[i].y);
}
sort(rect+1, rect+4, cmp);


if ((rect[1].x == rect[2].x && rect[2].x == rect[3].x && rect[1].x == rect[1].y+rect[2].y+rect[3].y)
|| (rect[1].x == rect[2].x && rect[1].x+rect[3].x == rect[3].x && rect[1].y+rect[2].y == rect[3].x)

|| (rect[1].x == rect[2].y && rect[1].x+rect[3].y == rect[3].x && rect[1].y+rect[2].x == rect[3].x)
|| (rect[1].y == rect[2].x && rect[1].y+rect[3].x == rect[3].x && rect[1].x+rect[2].y == rect[3].x)
|| (rect[1].y == rect[2].y && rect[1].y+rect[3].y == rect[3].x && rect[1].x+rect[2].x == rect[3].x))
printf("YES");
else printf("NO");
}

Và một số bài tập hình học cơ bản khác trên spoj.
B2. Bài tập mức nâng cao
1. Giao điểm cao nhất
Trong lễ hội bắn pháo hoa năm nay. Tiết mục trình diễn ánh sáng trong lễ khai mạc
của chủ nhà Đà Nẵng, có N tia laser được chiếu lên trời nhờ vào các đèn chiếu có
công suất rất lớn, vì vậy các tia laser này có thể đi rất xa. Các tia laser được chiếu lên
nằm trên cùng một mặt phẳng thẳng
đứng nên nếu không có 2 tia laser nào
song song với nhau thì 2 tia laser hoặc
là cắt nhau hoặc là không cắt nhau.
Các tia laser được biểu diễn bởi
3 số nguyên: Một số là tọa độ X ở
dưới đất của ngọn đèn chiếu, 2 số còn
lại là tọa độ của một điểm nào đó
thuộc tia laser này. Biết rằng không có
2 tia laser nào song song với nhau và
cũng không có tia Laser nào trùng với
mặt đất (mặt đất được coi như là đường thẳng y = 0). Không có đèn chiếu nào đặt
cùng một vị trí trên tục tọa độ.
Yêu cầu: Các nhà tổ chức buổi trình diễn muốn bạn cho biết với các tia laser sẽ được
chiếu lên trời như trong kế hoạch thì 2 tia laser nào cắt nhau tại điểm cao nhất.
Dữ liệu vào: Từ tệp văn bản ‘H_MAX.INP’ gồm:
• Dòng 1 ghi số nguyên N là số tia laser (2 ≤ n ≤ 100000).

• N dòng, mỗi dòng ghi 3 số nguyên xi, zi, ti với ý nghĩa là tia laser thứ i đi qua 2
điểm ( xi , 0 ) và ( zi , ti ) (|xi|, |zi| < 106, 0< ti ≤ 106).
Kết quả: Ghi ra tệp văn bàn ‘H_MAX.OUT’ như sau:
• Trong trường hợp không có 2 tia laser nào cắt nhau thì ghi ra duy nhất một số 1.
• Nếu tồn tại 2 tia Laser cắt nhau thì ghi số Hmax là độ cao lớn nhất giao điểm của
2 tia laser.
(hmax được ghi với độ chính xác 3 chữ số sau dấu phẩy).


Ví dụ:
H_MAX.INP
2
-1 -2 4
2 3 5

H_MAX.OUT
-1

H_MAX.INP
4
-1 -2 4
0 1 1
3 0 4
4 4 1

H_MAX.OUT
8.000

Thuật toán:
- Subtask 1: Duyệt chọn ra 2 tia, tìm điểm giao và tính chiều cao. Trong các chiều cao

đó chọn ra cặp 2 tia có chiều cao lớn nhất. Độ phức tạp thuật toán ~ O(N2). Làm cách
này thí sinh có không quá 40% số điểm của bài thi.
- Subtask 2: Bạn nên chú ý tới giá trị N – số tia laser, nó rất lớn (N ≤ 105). Ta gọi góc
tạo bởi một tia laser với trục nằm ngang (chiều dương là chiều ngược chiều kim đồng
hồ) là góc của tia đó.
function goc(x, y : extended) : extended;
begin

function theta(x, y : extended) : extended;
var

if x = 0 then goc := pi / 2
else if x * y > 0 then goc := arctan(y / x)
else if x * y < 0 then goc := pi + arctan(y / x);
end;

t : extended;
begin
t := y / (abs(x) + abs(y));
if x < 0 then t := 2 - t

Hàm tính góc theo đúng công thức thuần toán học bằng

else if y < 0 then t := 4 + t;

việc sự dụng hàm số arctan (mặc dù sử dụng hàm arctan

theta := t;

này có thể dẫn đến sai số lớn).


end;

Nhận xét: Nếu tia i và tia j giao nhau (với điều kiện góc của tia j là góc có giá trị gần
với góc của tia i nhất) thì độ cao giao điểm của hai tia đó sẽ lớn hơn độ cao giao điểm
của tia i với các tia khác tia j. Từ đó ta có thuật toán:
- Sắp xếp các tia theo thứ tự tăng dần (hoặc giảm dần) của góc tạo bởi các tia.
- Duyệt 1 lần theo thứ tự và xét chiều cao giao điểm của hai tia cạnh nhau
theo thứ tự mảng đó.
- Lưu lại giá trị lớn nhất tìm được.
Độ phức tạp thuật toán chủ yếu nằm ở bước sắp xếp các tia ~ O(NLogN).
Const
fi = 'H_MAX.inp';
fo = 'H_MAX.out';
maxn = 100000;
infinite = 100000000;
Type
diem = array[0..3] of extended;
Var

Procedure quicksort(l, r : longint);
var
i, j : longint;
x : extended;
begin
i := l; j := r;
x := a[t[(l + r) div 2], 0];


n : longint;

a : array[1..maxn] of diem;
t : array[1..maxn] of longint;
max : extended;
Procedure Doctep;
var
i : longint;
begin
assign(input,fi); reset(input);
readln(n);
fillchar(a, sizeof(a), 0);
for i := 1 to n do readln( a[i, 1], a[i, 2], a[i, 3]);
close(input);
end;
Function goc(x, y : extended) : extended;
begin
if x = 0 then goc := pi / 2
else if x * y > 0 then goc := arctan(y / x)
else if x * y < 0 then goc := pi + arctan(y / x);
end;
Procedure chuanbi;
var
i : longint;
begin
max := -infinite;
for i := 1 to n do
begin
a[i, 0] := goc(a[i, 2] - a[i, 1], a[i, 3]);
t[i] := i;
end;
end;

Procedure doicho(i, j : longint);
var
temp : longint;
begin
temp := t[i];
t[i] := t[j];
t[j] := temp;
end;

repeat
while a[t[i], 0] < x do inc(i);
while x < a[t[j], 0] do dec(j);
if i <= j then
begin
doicho(i, j);
inc(i);
dec(j);
end;
until i > j;
if i < r then quicksort(i, r);
if l < j then quicksort(l, j);
end;
Function giao(i, j : longint) : extended;
var
a1, a2, b1, b2 : extended;
begin
b1 := a[t[i], 1];
a1 := (a[t[i], 2] - b1) / a[t[i], 3];
b2 := a[t[j], 1];
a2 := (a[t[j], 2] - b2) / a[t[j], 3];

giao := (b2 - b1) / (a1 - a2);
end;
Procedure thuchien;
var
i : longint;
htemp : extended;
begin
quicksort(1, n);
for i := 1 to n - 1 do
begin
htemp := giao(i, i + 1);
if max < htemp then max := htemp;
end;
end;
procedure ghikq;
begin
assign(output, fo); rewrite(output);
if max > -infinite then write(max :0 :3)
else write( -1);
close(output);
end;
begin
doctep;
chuanbi;
thuchien;
ghikq;
end.

2. Xây cầu
Khu resort của thầy Minh trải khắp vịnh Hạ Long, với hàng trăm nghìn đảo lớn nhỏ.

Để quản lí hiệu quả hoạt động của khu resort, thầy Minh vẽ một bản đồ với hệ tọa độ
vuông góc oxy - mà ở đó gốc tọa độ (0,0) là nhà của mình. Khi đó đảo thứ i trong N
đảo có tọa độ là (xi,yi). Với số tiền T có được, thầy Minh đầu tư xây dựng một cây
cầu nối giữa hai đảo trong khu resort để tăng lợi nhuận kinh doanh. Vấn đề đặt ra bây
giờ là chọn xây cầu nối giữa hai đảo nào với số tiền đó mà cầu phải đảm bảo tính
thẩm mĩ và kiểm soát được độ rủi ro có thể xảy ra khi thi công? Biết độ thẩm mĩ


(dtmij) và độ rủi ro (dij) của cầu nối đảo có tọa độ (xi,yi) với đảo có tọa độ (xj,yj)
được tính theo công thức:
1
𝑑!" =  
(𝑥! − 𝑥𝑗)! + (𝑦! − 𝑦! )!
𝑇
!

(−1)!!! cos

𝑑𝑡𝑚!" = 𝑑!" +

𝑖𝜋
𝑗𝜋
+ (−1)!!! sin
𝑇
𝑇

!!!

Với dij < dik thì cầu nối cặp đảo (i,j) sẽ an toàn hơn cầu nối cặp đảo (i,k).
Với dtmij < dtmik tất nhiên cầu nối cặp đảo (i,k) sẽ đẹp hơn cầu nối cặp đảo (i,j).

Yêu cầu: Hãy chọn hai đảo để xây cầu sao cho ít rủi ro nhất.
Dữ liệu vào: Từ tệp văn bản ‘L_ISLAND.INP’ gồm:
• Dòng 1: Ghi số nguyên dương N, T – lần lượt là số đảo trong khu resort và số
tiền để xây cầu ( N ≤ 100000, T < 109).
• N dòng tiếp theo, dòng thứ i ghi số thực x và y là tọa độ của đảo thứ i. |x|<
10000000, |y| <10000000; Không có đảo nào trùng tọa độ.
Kết quả: Ghi ra tệp văn bản ‘L_ISLAND.OUT’ số nguyên duy nhất là độ rủi ro ít
nhất tìm được khi xây cầu. Lấy kết quả chính xác đến 3 chữ số thập phân.
L_ISLAND.INP
31
11
33
44

L_ISLAND.OUT
1.414

Thuật toán:
Bài toán thực chất là bài tìm cặp điểm gần nhất – một bài tập nổi tiếng về chủ đề hình
học. Ta có hai thuật toán:
• Duyệt tất cả các cặp điểm, tính dij và tìm max. Độ phức tạp thuật toán
O(N2)
• Thuật toán đề xuất bởi Preparata (Preparata) vào năm 1975 và được Shamos
trong các mô hình cây quyết định trong các thuật toán tối ưu. Thuật toán
này có độ phức tạp là O(NlogN).
Const
fi='L_ISLAND.INP';
fo='L_ISLAND.OUT';
Maxn=100001;
Vc=1.0e+15;

E=1.0e-4;
Type
ArrN=array[0..maxn] of double;
Var
N,t: longint;
X, y,xt,yt: arrN;
res: double;

Procedure Check(u,v: longint);
Var r: double;
Begin
if u<>v then
begin
r:=dis(u,v);
if rend;
End;
Procedure sorty(k,l: longint);
Var mid: longint;
r: double;


Function dis(i,j: longint): double;
Begin
dis:=sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j]));
End;
Procedure Doctep;
Var i: longint;
Begin
Readln(n,T);

For i:=1 to n do readln(x[i],y[i]);
End;
Procedure doi(var u,v: double);
Var w: double;
Begin
w:=u;
u:=v;
v:=w;
End;
Procedure sortx(k,l: longint);
Var r: double;
i,j: longint;
Begin
r:=x[(k+l) div 2];
i:=k; j:=l;
Repeat
while x[i]while x[j]>r do dec(j);
if i<=j then
begin
doi(x[i],x[j]);
doi(y[i],y[j]);
inc(i);
dec(j);
end;
Until i>j;
If kIf iEnd;
Procedure Merge(k,l: longint);

Var i,j,u: longint;
Begin
For i:=k to l do
begin
xt[i]:=x[i];
yt[i]:=y[i];
end;
j:=(k+l) div 2+1;
i:=k;
u:=k-1;
Repeat
inc(u);
if i>(k+l) div 2 then
begin
x[u]:=xt[j];
y[u]:=yt[j];
inc(j);
end
else if j>l then
begin
x[u]:=xt[i];
y[u]:=yt[i];
inc(i);
end
else
begin
if yt[i]<=yt[j] then

i, i1, i2, i3, i4: longint;
Begin

If k=l then exit;
mid:=(k+l) div 2;
r:=x[mid];
sorty(k,mid);
sorty(mid+1,l);
merge(k,l);
i1:=k; i2:=k; i3:=k; i4:=k;
For i:=k+1 to l do
if abs(x[i]-r)begin
check(i,i1); check(i,i2);
check(i,i3); check(i,i4);
i1:=i2; i2:=i3; i3:=i4;
i4:=i;
end;
End;
Procedure main;
Begin
Assign(input,FI); reset(input);
Assign(output,FO); rewrite(output);
Doctep;
Sortx(1,n);
Res:=vc;
Sorty(1,n);
Write(res/t:0:3);
Close(input); close(output);
End;
BEGIN
Main;
END.



begin
x[u]:=xt[i];
y[u]:=yt[i];
inc(i);
end
else
begin
x[u]:=xt[j];
y[u]:=yt[j];
inc(j);
end;
end;
Until u=l;
End;

3. Tổng độ dài đoạn thẳng
Cho N đoạn thẳng trên cùng một đường thẳng. Mỗi đoạn thẳng được xác định bởi 2
tọa độ điểm đầu và điểm cuối: X1 và X2. Tìm hợp của các đoạn thẳng này và tìm
tổng độ dài của chúng trong O(Nlog2N).
Thuật toán:
Sort tất cả các điểm đầu và điểm cuối của tất cả N đoạn thẳng. Nếu 1 điểm đầu và 1
điểm cuối có cùng tọa độ, ưu tiên điểm đầu trước. Lần lượt xử lý các điểm từ trái
sang phải.
unsigned segments_union_measure (const vector & a)
{
unsigned n = a.size();
vector for (unsigned i=0; i

{
x[i*2] = make_pair (a[i].first, false);
x[i*2+1] = make_pair (a[i].second, true);
}
sort (x.begin(), x.end());
unsigned result = 0;
unsigned c = 0;
for (unsigned i=0; i{
if (c && i)
result += unsigned (x[i].first - x[i-1].first);
if (x[i].second)
++c;
else
--c;
}
return result;
}

4. Tìm đường
Đất nước X đang gặp nguy hiểm, có một con quỷ từ đâu tới phá rối người dân nơi
đây. Vốn là một đất nước có tinh thần yêu nước, không phải chờ đợi lâu, một dũng sĩ
đã ngay lập tức xách gươm lên và đi đánh quỷ. Dũng sĩ cần đi từ điểm A thẳng tới
điểm B rồi tới điểm C (Nơi con quỷ đang phá rối). Nhưng không may, khi đến điểm


B, dũng sĩ quên mất đi tới C bằng con đường nào bởi ở B có 3 sự lựa chọn một là rẽ
vuông góc sang trái hoặc rẽ vuông góc sang phải hoặc đi thằng để tới C. Đúng lúc đó
có một con đại bàng bay ngang qua và thấy rõ được con quỷ ở hướng nào.
Giả sử nếu bạn là con đại bàng và được cho biết

trước tọa độ 3 điểm A, B, C, hãy nói cho dũng sĩ
nên rẽ trái, phải, hay đi thẳng nhé.
Input
Dòng 1, 2, 3 lần lượt chứa tọa độ 3 điểm A, B, C.
Mỗi dòng gồm 2 số nguyên là tọa độ tương ứng.
( |x|, |y| <= 10 ^9 )
Dòng 1, 2, 3 lần lượt chứa tọa độ 3 điểm A, B, C.
Mỗi dòng gồm 2 số nguyên là tọa độ tương ứng.
( |x|, |y| <= 10 ^9 )
Output
Gồm một dòng duy nhất.
In ra “RIGHT” nếu dũng sĩ nên rẽ phải, “LEFT” nếu rẽ trái và “TOWARDS” nếu đi
thằng.
Example
Test 1:
Input:
00
01
11
Output:
RIGHT
Test 2:
Input:
-1 -1
-3 -3
-4 -4
Output:
TOWARDS
Test 3:
Input:

-4 -6


×