Tải bản đầy đủ (.doc) (45 trang)

BÁO CÁO KẾT QUẢ SÁNG KIẾN KINH NGHIỆM: “Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin 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 (377.31 KB, 45 trang )

SỞ GD & ĐT VĨNH PHÚC
TRƯỜNG PT DTNT CẤP 2-3 VĨNH PHÚC

BÁO CÁO KẾT QUẢ
SÁNG KIẾN KINH NGHIỆM
Tên sáng kiến kinh nghiệm: “Một số phương pháp
hình học cơ bản để giải quyết các bài toán Tin học”
Tác giả sáng kiến: Nguyễn Đăng Hiệp
Mã sáng kiến: 04.62.01

Vĩnh Phúc, năm 2020


MỤC LỤC

Trang
1. Lời giới thiệu.............................................................................................1
2. Tên sáng kiến:...........................................................................................1
3. Tác giả sáng kiến:......................................................................................1
4. Chủ đầu tư tạo ra sáng kiến:........................................................................1
5. Lĩnh vực áp dụng sáng kiến:.......................................................................1
6. Ngày sáng kiến được áp dụng lần đầu hoặc áp dụng thử...............................2
7. Mô tả bản chất của sáng kiến:.....................................................................2
7.1. Về nội dung của sáng kiến:.........................................................................2
7.1.1. Thực trạng của vấn đề mà sáng kiến cần giải quyết............................2
7.1.2. Các giải pháp:......................................................................................2
7.2. Về khả năng áp dụng của sáng kiến:........................................................39
8. Những thông tin cần được bảo mật:...........................................................39
9. Các điều kiện cần thiết để áp dụng sáng kiến:............................................39
10. Đánh giá lợi ích thu được của sáng kiến...................................................39
11. Danh sách những tổ chức đã tham gia áp dụng sáng kiến…………………..42



12. Tài Liệu Tham Khảo……………………………………………………… 43


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
BÁO CÁO KẾT QUẢ
NGHIÊN CỨU, ỨNG DỤNG SÁNG KIẾN
1. Lời giới thiệu
Các bài toán tin rất đa dạng và phong phú và thể loại, tuy nhiên để áp dụng
và giải quyết các bài toán này yêu cầu học sinh phải nắm vững về kiến thức toán
học. Trong chương trình phổ thông, môn Tin học được đưa vào giảng dạy chính
khoá từ năm học 2006 - 2007. Lớp 11 các em sẽ được tiếp cận với ngôn ngữ lập
trình Pascal, một trong những ngôn ngữ lập trình được chọn giảng dạy không chỉ ở
các trường THPT mà còn được đưa vào giảng dạy ở các trường Đại học. Ngôn ngữ
lập trình Pascal còn được chọn là ngôn ngữ lập trình trong các kỳ thi OLYMPIC
Tin học Quốc tế.
Đối với người lập trình, kiến thức tối thiểu là biết được cách tổ chức cấu trúc
dữ liệu và nêu được thuật toán để giải bài toán, phát hiện bài toán và áp dụng các
phương pháp giải các dạng toán đều phải qua một quá trình hình thành và tích luỹ.
Xin nêu “Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin
học” trong chương trình phổ thông và nêu một số bài toán nâng cao.
2. Tên sáng kiến:
“Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học”
3. Tác giả sáng kiến:
- Họ và tên: Nguyễn Đăng Hiệp
- Địa chỉ: Trường Phổ Thông Dân Tộc Nội Trú Cấp 2-3 Vĩnh Phúc
- Số điện thoại: 0975.486.964 E_mail:
4. Chủ đầu tư tạo ra sáng kiến: Nguyễn Đăng Hiệp
5. Lĩnh vực áp dụng sáng kiến:
Đề tài giúp học sinh tổng hợp và phát triển thuật toán sao cho gần gũi với tư duy

của học sinh phổ thông.
Đây cũng là một vấn đề mới vì: Muốn hiển thị được một điểm ảnh hay hoạt động
của con chuột máy tính đúng toạ độ, các lập trình viên đã phải lập trình và căn đúng

1


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
toạ độ cho con chuột… Như vậy các phương pháp giải quyết bài toán này đã được
nghiên cứu từ rất lâu, các bài toán này được các nhà nghiên cứu về toán học và lý
thuyết Tin học đưa ra. Các vấn đề đưa ra là giúp học sinh sự tổng hợp và phát triển
thuật toán gần gũi với tư duy của mình
6. Ngày sáng kiến được áp dụng lần đầu hoặc áp dụng thử
Sáng kiến được áp dụng với 100 học sinh khối 11 trong trường bắt đầu từ
học kỳ 1 năm học 2019 - 2020
7. Mô tả bản chất của sáng kiến:
7.1. Về nội dung của sáng kiến:
7.1.1. Thực trạng của vấn đề mà sáng kiến cần giải quyết.
Như chúng ta đã biết lập trình trong Tin học là một phần học rất khó, đòi hỏi
nhiều đến sự phát triển tư duy để tìm tìm thuật toán và đòi hỏi học sinh phải nắm
vững kiến thức về mặt toán học nên đa số học sinh không say mê với môn học này.
Vì vậy vai trò của giáo viên là rất quan trọng, làm thế nào để cho học sinh có hứng
thú, không khí lớp học thoải mái. Giáo viên phải có phương pháp truyền đạt lôi
cuốn học sinh thông qua gợi mở, thuyết minh, giải quyết vấn đề… Nhưng vẫn đảm
bảo thời gian, và nội dung cơ bản của giờ học.
Song do tình trạng chung hiện nay học sinh đa số mất gốc về mặt toán học,
cơ sở vật chất để phục vụ giảng dạy còn thiếu vì vậy ảnh hưởng rất nhiều đến khả
năng tiếp thu và sự say mê của học sinh khi học Tin học. Cho nên hiệu quả giờ học
không cao.
7.1.2. Các giải pháp:

Để học sinh đạt được mục đích, yêu cầu của chuẩn kiến thức, tôi đã tìm tòi, nghiên
cứu, hướng dẫn học sinh thảo luận một số phương pháp hình học để giải quyết bài
toán. Giúp các em xây dựng được một số thuật toán điển hình ở dạng đơn giản và
nâng cao. Tiết học trở nên sinh động hơn và giáo viên không đóng vai trò là người
xây dựng lý luận mà học sinh là người chủ động để giải quyết các vấn đề.

2


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
Để giờ dạy đạt hiệu quả cao và tạo hứng thú học tập của học sinh tôi đã chuẩn bị
các slide (bằng phần mềm Microsoft Power Point) để trình chiếu và sử dụng các
phần mềm để mô phỏng các thuật toán.
Sau đây là một số phương pháp hình học cơ bản để giải quyết các bài toán
Tin học thông qua các bài toán điển hình dưới đây:
1- Vị trí tương đối của điểm so với đường thẳng và đoạn thẳng
Bài toán 1: Tìm vị trí tương đối của điểm M(x 0; yo) so với đường thẳng đi qua 2
điểm A(x1; y1) và B(x2; y2) (với x1  x2)
Phương trình đường thẳng qua A, B là (y-y1)(x2 – x1) = (y2-y1)(x-x1)
hay là: (y2-y1)*x - (x2-x1)*y + y1*x2 –x1* y2 = 0.
+) Nếu (y2-y1)*x0 - (x2-x1)*y0 + y1*x2 –x1* y2 > 0 thì điểm M nằm phía trên cao hơn
đường thẳng AB.
+) Nếu (y2-y1)*x0 - (x2-x1)*y0 + y1*x2 - x1* y2 < 0 thì điểm M nằm phía dưới thấp
hơn đường thẳng AB.
Bài toán 2: Điểm M(x0,yo) có thuộc đoạn thẳng nối 2 điểm A(x 1,y1) và B(x2,y2) hay
không (với x1  x2)
Điểm M(x0,yo) thuộc đoạn thẳng nối 2 điểm A(x1,y1) và B(x2,y2) (với x1 
x2) nếu thoả mãn: (y2-y1)*x0 - (x2-x1)*y0 + y1*x2 - x1* y2 = 0 và Min(x1, x2)  x0 
Max(x1, x2)
2- Giao của các Đoạn thẳng

Bài toán 3: Cho 2 đoạn thẳng AB và CD, toạ độ các đầu mút là A(x 1,y1),
B(x2,y2), C(x3,y3) và D(x4,y4). Hãy xét xem hai đoạn thẳng này có giao nhau không.
a) Cách 1:
- Tìm giao điểm của 2 đường thẳng AB và CD bằng cách giải hệ gồm 2 phương
trình:
(y2-y1)*x - (x2-x1)*y + y1*x2 - x1* y2= 0 (1)
(y4-y3)*x - (x4-x3)*y + y3*x4 - x3* y4 = 0 (2)

3


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
- Sau đó kiểm tra xem giao điểm có thuộc 2 đoạn thẳng AB và CD hay không
Tìm giao điểm (nếu có) của hai đường thẳng trong mặt phẳng tọa độ có
phương trình lần lượt là a1x + b1y = c1 và a2x + b2y = c2.
Bài toán này có thể dễ dàng giải được bằng việc sử dụng phương pháp đã biết ở
phổ thông. Cụ thể:
D: = a1*b2 - a2*b1; Dx : = c1*b2 - c2*b1; Dy: = a1*c2 - a2*c1;
If D < > 0 then Writeln (' x = ', Dx/D : 4:2, 'y = ', Dy/D: 4:2)
else If (Dx = 0) and (Dy = 0) then Writeln (' H ai đường thẳng trùng nhau’)
b) Cách 2:
Trước hết xét bài toán phụ: Trên mặt phẳng toạ độ cho tam giác ABC, đi trên cạnh
từ A đến B rồi đến C theo chiều nào (ngược chiều kim đồng hồ hay thuận chiều kim
đồng hồ) với giả thiết không có cạnh nào song song trục tung.
Ta thấy không mất ý nghĩa của bài toán khi ta quay toàn bộ tam giác một cách tuỳ
ý. Vì vậy đầu tiên ta giả sử A là đỉnh có hoành độ bé nhất (x2 > x1,x3 > x1) thì
hệ số góc đường thẳng AB là: k1= (y2- y1)/ (x2 - x1)
hệ số góc đường thẳng AC là: k2= (y3- y1)/ (x3 – x1)
Ký hiệu dy1 = (y2 – y1); dx1 = (x2 - x1) > 0
dy2 = (y3 – y1); dx2 = (x3 –x1) > 0

Do đó đi trên cạnh từ A đến B rồi đến C theo chiều ngược chiều kim đồng hồ khi k 2
> k1 hay là dy2* dx1 > dx2 *dy1 ( mã hoá là chiều +1 )
Ngược lại đi trên cạnh từ A đến B rồi đến C theo chiều thuận chiều kim đồng hồ khi
k2 < k1 hay là dy2* dx1 < dx2 *dy1 ( mã hoá là chiều -1 )
Trong trường hợp A, B, C thằng hàng thì dy 2* dx1 = dx2 *dy1; khi đó ta phải xem
xét chi tiết hơn: điểm nào nằm giữa 2 điểm còn lại?
+ Nếu B, A, C thì dx1*dx2 < 0 hoặc dy1*dy2 < 0, góc quay từ AB tới AC là -180 độ,
vậy quy ước đi từ A đến B rồi đến C là thuận chiều kim đồng hồ (mã hoá là chiều
-1)

4


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
+ Nếu A, B, C thì qua A kẻ đường thẳng nằm ngang At, gọi hình chiếu của B, C
xuống At lần lượt là H, K thì AB 2 =AH2 + BH2 < AK2 + CK2 nên dx12 +dy12 < dx22 +
dy22, ta quy ước chiều đi từ A đến B rồi đến C là ngược chiều kim đồng hồ (mã hoá
là chiều +1).
+ Nếu B, C, A thì quy ước (mã hoá là chiều 0)
Uses crt;
const max = 10;
type diem = record x,y: integer end;
doanthang = record p1,p2: diem end;
var l: array[1..2] of doanthang;
procedure nhap;
var i: integer;
begin
for i:=1 to 2 do
begin
write('toado(x1,y1)(x2,y2)doanthu',i,': ');

readln(l[i].p1.x,l[i].p1.y,l[i].p2.x,l[i].p2.y);
end;
end;
function chieu(p1,p2,p3: diem): integer;
var dx1,dx2,dy1,dy2: integer;
begin
dx1: = p2.x-p1.x;
dy1: = p2.y-p1.y;
dx2: = p3.x-p1.x;
dy2: = p3.y-p1.y;
if dx1*dy2>dy1*dx2 then chieu: = 1;
if dx1*dy2
5


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
if dx1*dy2=dy1*dx2 then
begin
if (dx1*dx2<0)or(dy1*dy2<0) then chieu: = -1
else
if (dx1*dx1+dy1*dy1>=dx2*dx2+dy2*dy2) then chieu: = 0
else cq: = 1;
end;
end;
function giaonhau(l1,l2: doanthang): boolean;
begin
giaonhau: = (chieu(l1.p1,l1.p2,l2.p1)*chieu(l1.p1,l1.p2,l2.p2)<=0)
and (chieu(l2.p1,l2.p2,l1.p1)*chieu(l2.p1,l2.p2,l1.p2)<=0);
end;

BEGIN
clrscr;
nhap;
if giaonhau(l[1],l[2]) then writeln('giao nhau')
else writeln('khong giao nhau ');
readln;
END.
Có được điều đó là vì đoạn thẳng AB giao với đoạn thẳng CD khi và chỉ khi
đi theo ABC ngược chiều với ABD và đi theo CDA ngược chiều với CDB
3- Vi trí của Điểm so với Đa giác
Bài toán 4: Cho đa giác gồm N đỉnh d[1],d[2],...,d[n] và điểm M. Hãy xác
định vị trí tương đối của M với miền trong của đa giác (M nằm ngoài hay nằm
trong đa giác)
Thuật toán: Kẻ đoạn thẳng MN song song trục hoành sao cho hoành độ của N lớn
hơn hoành độ max của các hoành độ đỉnh đa giác. Xét giao các cạnh của đa giác

6


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
với đoạn thẳng MN. Số giao điểm là lẻ thì M trong đa giác, chẵn thì M ngoài đa
giác
Có một trở ngại là gặp những trường hợp: Đỉnh d[i+1] của cạnh nằm trên
đoạn thẳng MN, thì cạnh d[i]-d[i+1] và cạnh d[i+1]-d[i+2] đều giao với đoạn MN,
hoặc cạnh d[i]-d[i+1] nằm trên đoạn thẳng MN thì cả 3 cạnh d[i-1]-d[i], d[i]-d[i+1],
d[i+1]-d[i+2] đều giao với MN nên xử lý như chương trình sau:
Ngoài ra ta cũng có thể giải bài toán này bằng cách chia đa giác thành n-2
tam giác rồi tính tổng diện tích của các tam giác ấy. Tuy nhiên phương pháp này dài
dòng, ta làm cách khác như sau: chia đa giác thành các hình thang bằng cách chiếu
các cạnh xuống trục hoành (hình vẽ).

Hình thang được xác lập bởi cạnh A [i] A[i+1]có diện tích là Abs (S) với
1
S= *  A[i]* x  A[i  1]* x  *  A[i]* y  A[i  1]* y 
2

Vậy S = S +  A[i ]* x  A[i  1]* x  *  A[i ]* y  A[i  1]* y  ; S =

1
Abs ( S )
2

Sau khi gán đỉnh A[n+1]:=A[1] ta tính diện tích toàn phần của đa giác như sau:
S: = 0;
For i: =1 to N do

S: = (1/2) * Abs(S);

Chú ý :
1. Hoàn toàn tương tự ta có thể tìm diện tích của đa giác bằng cách chiếu các cạnh
xuống trục tung.

7


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
2. Nếu thay bước gán S: = (1/2) * abs (S) bởi S: = S/2 thì dấu của S là dương hay
âm sẽ cho ta biết chiều đánh số của các đỉnh theo thứ tự từ 1, 2,.... N là ngược hay
xuôi chiều kim đồng hồ.

Uses crt;

const max = 100;
fi = 'dagiac.inp';
type diem = record x,y: integer; end;
doanthang = record p1,p2: diem; end;
var l: array[1..2] of doanthang;
d: array[0..max+2] of diem;
m: diem;
n: byte;
maxx: integer;
function chieu(p1,p2,p3: diem): integer;
{Xac dinh chieu di tu p1->p2->p3}
var dx1,dx2,dy1,dy2: integer;
begin
dx1: = p2.x-p1.x;
dy1: = p2.y-p1.y;
dx2: = p3.x-p1.x;
dy2: = p3.y-p1.y;
if dx1*dy2>dy1*dx2 then chieu: = 1;

8


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
if dx1*dy2if dx1*dy2=dy1*dx2 then
begin
if (dx1*dx2<0) or (dy1*dy2<0) then chieu: = -1
else
if (dx1*dx1+dy1*dy1>=dx2*dx2+dy2*dy2) then chieu: = 0
else chieu: = 1;

end;
end;
function giaonhau(l1,l2: doanthang): boolean;
begin
giaonhau: = (chieu(l1.p1,l1.p2,l2.p1)*chieu(l1.p1,l1.p2,l2.p2)<=0)
and (chieu(l2.p1,l2.p2,l1.p1)*chieu(l2.p1,l2.p2,l1.p2)<=0);
end;
procedure nhap;
var i: integer;
f: text;
begin
assign(f,fi);
reset(f);
readln(f,n);
maxx: = -maxint;
for i:=1 to n do
begin
readln(f,d[i].x,d[i].y);
if d[i].x>maxx then maxx: = d[i].x;
end;
readln(f,m.x,m.y);

9


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
close(f);
end;
function thuoc(p: diem;lp: doanthang): boolean;
var a,b,c: real;

function min2(a,b: real): real;
begin
if aend;
function max2(a,b: real): real;
begin
if a>b then max2: = a else max2: = b;
end;
begin
a: = lp.p2.y-lp.p1.y;
b: = lp.p1.x-lp.p2.x;
c: = lp.p1.y*lp.p2.x-lp.p1.x*lp.p2.y;
if (a*p.x+b*p.y+c=0) and (min2(lp.p1.x,lp.p2.x)<=p.x)
and (max2(lp.p1.x,lp.p2.x)>=p.x) then thuoc: = true
else thuoc: = false;
end;
function trong(p: diem): boolean;
var dem,i,j: integer;
lt,lp: doanthang;
begin
dem: = 0;
d[0]: = d[n];
d[n+1]: = d[1];
d[n+2]: = d[2];

10


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
lt.p1: = p;

lt.p2.y: = p.y;
lt.p2.x: = maxx+1;
for i:=1 to n do
begin
lp.p1: = d[i];
lp.p2: = d[i+1];
if thuoc(p,lp) then
begin
trong: = true;
exit;
end;
if giaonhau(lp,lt) and (lp.p1.y<>p.y) and (lp.p2.y<>p.y) then inc(dem);
if giaonhau(lp,lt) and ((lp.p1.y=p.y) and (lp.p2.y=p.y))
and ((d[i-1].y-d[i].y)*(d[i+2].y-d[i].y)<0)
then inc(dem);
if giaonhau(lp,lt) and (d[i+1].y=p.y)
and ((d[i].y-p.y)*(d[i+2].y-p.y)<0)
then inc(dem);
end;
trong: = ((dem mod 2)=1);
end;
BEGIN
clrscr;nhap;
if trong(m) then writeln('diem m nam trong da giac ')
else writeln('diem m o phia ngoai da giac ');
readln;
END.

11



Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
4- Đa giác lồi
Bài toán 5: Kiểm tra một đa giác có là đa giác lồi hay không. Để kiểm tra
tính lồi của đa giác, với mọi cạnh nối đỉnh i - với đỉnh (i+1) (i từ 1 đến n, đỉnh n+1
coi như đỉnh 1) mọi đỉnh j (j từ 1 đến n) và đỉnh (i+2) phải luôn luôn cùng phía so
với đường thẳng chứa cạnh i-(i+1)
Uses crt;
const max = 20;
fi= 'dg_loi.inp';
type toado = array[1..max] of real;
var x,y : toado;
n: word;
procedure input;
var i : word;
f : text;
begin
assign(f,fi); reset(f);
readln(f,n);
for i:=1 to n do
readln(f,x[i],y[i]);
close(f);
end;
function cungfia(x1,x2,x3,x4,y1,y2,y3,y4: real):boolean;
var d1,d2: real;
begin
d1: = (y3-y1)*(x2-x1)-(x3-x1)*(y2-y1);
d2: = (y4-y1)*(x2-x1)-(x4-x1)*(y2-y1);
cungfia:=d1*d2>=0;
end;


12


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
function dg_loi: boolean;
var

i,j,k,l : word;

begin
for i:=1 to n do
begin
k: = i+2;
l: = i+1;
if k=n+1 then k: = 1;
if l=n+1 then l: = 1;
for j:=1 to n do
if (j<>i) and ( not
cungfia(x[i],x[l],x[j],x[k],y[i],y[l],y[j],y[k]))
then
begin
dg_loi: = false;
exit;
end;
end;
dg_loi: = true;
end;
BEGIN
clrscr;

input;
if dg_loi then writeln('da giac loi ')
else writeln('da giac khong loi ');
END.
5- Tìm đường bao lồi chứa tập điểm cho trước

13


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
Bài 6: Cho N điểm a1,a2,..., an trên mặt phẳng. Các điểm có toạ độ nguyên
và không có 3 điểm nào thẳng hàng. Hãy viết chương trình xác định một đa giác
không tự cắt có các đỉnh là một số điểm trong n điểm đã cho và chứa tất cả các
điểm còn lại, đồng thời có chu vi nhỏ nhất. Hãy tính diện tích đa giác này
Dữ liệu vào cho trong file DAGIAC.INP gồm n+1 dòng
- Dòng 1 chứa số N.
- N dòng tiếp theo: dòng i trong n dòng này chứa toạ độ (xi,yi) của điểm ai
Dữ liệu ra ghi vào file DAGIAC.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 và s là
diện tích của nó.
- Dòng i+1 (1  i  k ) ghi toạ độ của đỉnh thứ i của đa giác.
Ghi chú: các số thực có phần thập phân có 2 số lẻ
Ví dụ
DAGIAC.INP
5
0 1
4 4
04
40
22

DAGIAC.OUT
4 15.12 14.00
44
04
01
3

0

14


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
* Phương pháp 1: Dựa vào định nghĩa đa giác lồi
Trước hết cần chú ý đa giác không tự cắt có các đỉnh là một số điểm trong n
điểm đã cho và chứa tất cả các điểm còn lại, đồng thời có chu vi nhỏ nhất đó chính
là đường bao lồi chứa các điểm đã cho mà các đỉnh của bao lồi thuộc tập đỉnh đã
cho.
Để tìm bao lồi này theo định nghĩa đa giác lồi, ta thực hiện như sau:
+ Tìm 2 điểm: x0, x1 chắc chắn thuộc bao lồi: đó là 2 điểm nằm trên một
đường thẳng d sao cho mọi điểm còn lại đều ở cùng một phía của d.
+ Tìm điểm tiếp theo là x i (chọn trong các điểm còn lại chưa trong bao lồi)
sao cho với mọi điểm j luôn cùng phía với x0 so với đường thẳng qua xi, x1.
+ Lại coi j là xi và tiếp tục tìm j mới cho đến khi không còn tìm được nữa
Uses crt;
const max

= 100;

fi = 'baoloi.inp';

fo = 'baoloi.out';
type toado = array[1..max] of real;
var x,y,ly : toado;
b : array[1..1000] of boolean;
ds: array[1..1000] of integer;
n,top : integer;
f : text;
procedure input;
var i: integer;
f : text;
begin
assign(f,fi);
reset(f);
readln(f,n);
15


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
for i:=1 to n do
readln(f,x[i],y[i]);
close(f);
end;
function cungfia(x1,x2,x3,x4,y1,y2,y3,y4: real): boolean;
var d1,d2: real;
begin
d1: = (y3-y1)*(x2-x1)-(x3-x1)*(y2-y1);
d2: = (y4-y1)*(x2-x1)-(x4-x1)*(y2-y1);
cungfia:=d1*d2>=0;
end;
function timhaidiem(var i,j: integer): boolean;

var k,l: integer;
begin
for k:=1 to n do
for l:=1 to n do
if (k-i)*(k-j)*(l-i)*(l-j)<>0 then
if not cungfia(x[i],x[j],x[k],x[l],y[i],y[j],y[k],y[l]) then
begin
timhaidiem: = false;
exit;
end;
timhaidiem: = true;
end;
function dientich: real;
var s,min: real;
i,j: integer;
begin
16


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
ly: = y;
min: = 10000; { tinh tien da giac doc truc oy sao cho
da giac nam hoan toan phia tren truc ox}
for i:=1 to top do
if y[ds[i]]if min<0 then
for i:=1 to top do y[ds[i]]: = y[ds[i]] - min;
s: = 0;
for i:=1 to top do
begin

j: = i+1;
if i=top then j: = 1;
s: = s+((x[ds[j]]x[ds[i]])*(y[ds[j]]+y[ds[i]]))/2;
end;
dientich: = abs(s);
end;
function timk: integer; { tim diem tiep theo cua duong bao quanh }
var

i,j,l,k: integer;
ok: boolean;

begin
timk:=0;
i: = ds[top-1];
j: = ds[top];
for k:=1 to n do
if not b[k] then
begin
ok: = false;
for l:=1 to n do
17


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
if (l<>k) then
if not cungfia(x[j],x[k],x[i],x[l],y[j],y[k],y[i],y[l]) then
begin
ok: = true;
break;

end;
if not ok then
begin
timk: = k;
exit;
end;
end;
end;
procedure work2; { tim duong da giac loi chua tap diem da cho }
var

i,j,k,l,t: integer;
min: real;

ok: boolean;
begin
fillchar(b,sizeof(b),false);
for i:=1 to n do
begin
ok: = true;
for j:=1 to n do
if (j<>i) and timhaidiem(i,j) then
begin
ds[1]: = i;
ds[2]: = j;
top: = 2;
18


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học

b[i]: = true;
b[j]: = true;
ok: = false;
break;
end;
if not ok then break;
end;
repeat
k: = timk;
if k<>0 then
begin
inc(top);
ds[top]

:= k;

b[k]

:= true;

end;
until k=0;
end;
function chuvi: real;
var i,j: integer;
c: real;
begin
c: = 0;
for i:=1 to top do
begin

j: = i+1;
if i=top then j: = 1;
c: = c + sqrt(sqr(x[ds[j]]-x[ds[i]])+
sqr(y[ds[j]]-y[ds[i]]));
19


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
end;
chuvi: = c;
end;
BEGIN
clrscr;input;
work2;
assign(f,fo); rewrite(f);
writeln(f,top,' ',chuvi:8:2,' ',dientich:8:2);
for n:=1 to top do writeln(f,x[ds[n]]:4:0,' ',ly[ds[n]]:4:0);
close(f);
END.
* Phương pháp 2: (wrap: bọc gói)
Trước hết chọn một điểm chắc chắn thuộc bao lồi (thí dụ điểm có tung độ
nhỏ nhất), gọi điểm này là điểm A. Kẻ tia Ax cùng chiều dương của trục hoành.
Quay tia Ax xung quanh A một góc V cho đến khi chạm điểm đầu tiên của tập điểm
đã cho, đó là điểm thuộc bao lồi. Lại gọi điểm này là A, lại tạo tia Ax, quay góc V 1
cho đến khi chạm điểm đầu tiên của tập điểm thì điểm mới này lại là một điểm của
bao lồi. Quá trình cứ tiếp diễn như vậy cho đến khi điểm mới tìm được trùng với
điểm A ban đầu.
Chú ý rằng luôn luôn có V 1 > = V. Mặt khác, thực chất chúng ta cũng không
quay tia Ax mà “quay một cách hình thức” như sau: Ta tính tất cả các góc V b tạo
bởi tia Ax và tia AB (B là mọi điểm chưa thuộc bao lồi), V b nào nhỏ nhất sẽ được

chọn làm V và điểm B tương ứng sẽ là điểm được đưa vào bao lồi.
Điều chú ý thứ hai là: Đặt dy=(yb - ya); dx=(xb - xa ), ay=|dy|, ax=|dx|
Để tính các góc V, đáng lẽ tính ta tính V= arctang(dy/dx ), nhưng ta thay bằng tính
t=dy/(ax+ay) vì có thể chứng minh khi t và V dương thì t đồng biến theo V (V tăng
thì t cũng tăng). Nhờ đó có thể xử lý tốt trong những trường hợp sau:
+ Nếu dx = 0 thì cho góc=90 độ
20


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
+ Nếu dy = 0 và dx >0 thì góc = 0 độ
+ Nếu dy = 0 và dx <0 thì cho t=90 độ và góc = 2*t = 180 độ
+ Nếu góc là tù thì góc = (2 - t) * 90 độ
+ Nếu góc > 180 độ thì góc = (4+t) * 90 độ ( t<0 vì trong trường hợp này dy<0)
Ngoài ra khi đọc chương trình dưới đây cũng cần lưu ý kỹ thuật dùng biến
rất tiết kiệm bằng cách: mỗi khi được một đỉnh thuộc bao lồi thì chứa ngay vào
phần đầu của mảng P chứa tập điểm đã cho. Cụ thể nếu đã được m đỉnh của bao lồi
thì m phần tử đầu của mảng P là những đỉnh này, để tìm đỉnh thứ m+1 của bao lồi
chỉ cần duyệt trên mảng P từ m+1 đến n+1 (n+1 là đỉnh 1 ). Giả sử tìm được đỉnh
thứ m+1 của bao lồi là phần tử thứ i thì đổi chỗ phần tử thứ i này cho phần tử thứ
m+1 của P.
Uses crt;
const max

= 20;

fi = 'baoloi.inp';
fo = 'baoloi.out';
type diem = record x,y: real end;
dagiac = array[1..max] of diem;

var p: dagiac;
n,i,m : integer;
f: text;
procedure input;
var i : integer;
f: text;
begin
assign(f,fi); reset(f);
readln(f,n);
for i:=1 to n do
readln(f,p[i].x,p[i].y);
21


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
close(f);
end;
function theta(i,j: byte): real;
var dx,dy,ax,ay,t: real;
begin
if i=n+1 then i:=1;
if j=n+1 then j:=1;
dx: = p[j].x-p[i].x;
ax: = abs(dx);
dy: = p[j].y-p[i].y;
ay: = abs(dy);
if (dx=0) then
begin theta: = 0;exit;end
else
if (dy=0) then

begin theta: = 90;exit;end
else t: = dy/(ax+ay);
if dx<0 then t: = 2-t
else if dy<0 then t: = t+4;
theta: = t*90;
end;
function wrap: integer;
var i,min,m: integer;
minangle,v,goc: real;
t: diem;
begin
min: = 1;
for i:=2 to n do
22


Một số phương pháp hình học cơ bản để giải quyết các bài toán Tin học
if p[i].ym: = 0;
p[n+1]: = p[min];
minangle: = 0.0;
repeat
m: = m+1;
t: = p[m];
p[m]: = p[min];
p[min]: = t;
min: = n+1;
v: = minangle;
minangle: = 360.0;
for i:=m+1 to n+1 do

begin
goc: = theta(m,i);
if goc>=v then {có dầu bằng vì xét cả trường hợp các điểm trên bao lồi thẳng
hàng }
if gocbegin
min: = i;
minangle: = goc;
end;
end;
until min = n+1;
wrap: = m;
end;
BEGIN
clrscr;
23