ỨNG DỤNG THUẬT TOÁN TÌM DIỆN TÍCH ĐA GIÁC ĐỂ LẬP TRÌNH GIẢI MỘT SỐ BÀI TOÁN VỀ HÌNH HỌC Thuật toán hiệu quả tìm diện tích đa giác đã được nhiều tác giả nêu ra.. Tuy nhiên trong bài viết
Trang 1ỨNG DỤNG THUẬT TOÁN TÌM DIỆN TÍCH ĐA GIÁC
ĐỂ LẬP TRÌNH GIẢI MỘT SỐ BÀI TOÁN VỀ HÌNH HỌC
Thuật toán hiệu quả tìm diện tích đa giác đã được nhiều tác giả nêu
ra Tuy nhiên trong bài viết này tôi chỉ xin nêu ra một số bài toán mà nếu ứng dụng thuật toán tìm diện tích đa giác để giải chúng sẽ rất hiệu quả Trước hết, ta sẽ nhắc lại thuật toán này
Bài toán: Tính diện tích đa giác (lồi hoặc lõm và không tự cắt) gồm n đỉnh A
[1], A[2], , A[n] (n>2)
Thuật toán: Ta 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 phức tạp, 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 (hoặc trục tung) Hình thang được xác định bởi cạnh A[i]A[i+1] có diện tích là Abs(S) với :
S = (A[i].x - A [i+1].x).(A[i].y + A[i+1].y) /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 := S + (A[i].x - A [i+1].x).(A[i].y + A[i+1].y);
S: = (1/2) * Abs(S);
Sau đây là một số ví dụ áp dụng thuật toán vừa trình bày
Bài 1 Kiểm tra tính lồi lõm của một đa giác.
Trong mặt phẳng toạ độ có n điểm có toạ độ tương ứng là (x1, y1), (x2, y2) , , (xn, yn) Biết rằng n điểm đã cho theo thứ tự tạo thành các đỉnh của một đa giác không tự cắt Yêu cầu: hãy kiểm tra đa giác lồi hay lõm
Trang 2Dữ liệu vào ghi trong file DAGIAC.INP: dòng đầu ghi một số n (n>2), n dòng tiếp theo, trên dòng thứ i ghi hai số thực theo thứ tự là hoành độ và tung độ của đỉnh thứ i-1 của đa giác
Dữ liệu ra ghi vào file DAGIAC.OUT gồm một số 0 hoặc 1, ghi 0 nếu đa giác lõm và ghi 1 nếu đa giác lồi
Thuật toán: Gọi diện tích của đa giác là S0 Ta sẽ so sánh S0 với các Si, trong đó Si là diện tích của đa giác thu được từ đa giác ban đầu sau khi bỏ
đi đỉnh thứ i (i=1, 2, , n) Nếu i sao cho Si > S0 thì đa giác đã cho lõm (tại đỉnh thứ i), ngược lại thì đa giác đã cho lồi
Toàn văn chương trình như dưới đây:
{Kiem tra mot da giac loi hay lom}
type
diem=record
x,y:real;
end;
var a:array [1 100] of diem;
n,vt:integer;
s0,s1:real;
procedure init;
var f:text;i:byte;
begin
assign(f,'dagiac.inp');
reset(f);
readln(f,n);
{while not eof(f) do}
for i:= 1 to n do
begin
read(f,a[i].x);
read(f,a[i].y);
end;
close(f);
a[n+1]:=a[1];
{Tinh dien tich da giac}
s0:=0;
for i:=1 to n do
s0:=s0+(a[i+1].x-a[i].x)*(a[i+1].y+a[i].y);
s0:=abs(s0)/2
end;
Procedure Inkq(i:byte);
var f:text;
begin
assign(f,'dagiac.out');
Trang 3rewrite(f);
write(f,i);
close(f);
end;
Procedure resolve;
var b:array [1 50] of diem;
i,j,k:byte;
Begin
for i:=1 to n do
begin
for j:=1 to i-1 do b[j]:=a[j];
for j:=i+1 to n+1 do b[j-1]:=a[j];
s1:=0;
for j:=1 to n-1 do
s1:=s1+(b[j+1].x-b[j].x)*(b[j+1].y+b[j].y);
s1:=abs(s1)/2;
if s1>s0 then
begin
inkq(0);
halt
end;
end;
inkq(1);
End;
begin
init;
resolve;
end.
Bài 2 Chia đa giác (mô phỏng đề thi HS giỏi quốc gia lớp 12, bảng B, năm 1999-2000).
Trong mặt phẳng toạ độ có n điểm có toạ độ tương ứng là (x1, y1), (x2, y2) , , (xn, yn) Biết rằng n điểm đã cho theo thứ tự tạo thành các đỉnh của một đa giác không tự cắt Yêu cầu: hãy chia đa giác đã cho thành hai đa giác bởi một cạnh nối hai đỉnh không kề nhau sao cho diện tích của chúng chênh lệch nhau ít nhất
Dữ liệu vào ghi trong file DAGIAC.INP: dòng đầu ghi một số n (n>3), n dòng tiếp theo, trên dòng thứ i ghi hai số thực theo thứ tự là hoành độ và tung độ của đỉnh thứ i-1 của đa giác
Dữ liệu ra ghi vào file DAGIAC.OUT gồm hai số nguyên dương chỉ số thứ
tự của hai đỉnh được nối sao cho thoả mãn điều kiện đầu bài
Trang 4Thuật toán: Ta đưa ra thuật toán rất đơn giản như sau: thử tìm mọi cách
chia và ghi nhận lại cách chia tốt nhất Dễ thấy độ phức tạp của thuật toán trong trường hợp này là O(n3)
Toàn văn chương trình như dưới đây:
Program vd;
type
diem=record
x,y:real;
end;
var a:array [1 100] of diem;
n,vt1,vt2:integer;
s0,s1,del:real;
procedure init;
var f:text;i:byte;
begin
assign(f,'dagiac.inp');
reset(f);
readln(f,n);
for i:= 1 to n do
begin
read(f,a[i].x);
read(f,a[i].y);
end;
close(f);
a[n+1]:=a[1];
s0:=0;
for i:=1 to n do
s0:=s0+(a[i+1].x-a[i].x)*(a[i+1].y+a[i].y);
s0:=abs(s0)/2;
del:=s0;
end;
Procedure resolve;
var b:array [1 50] of diem;
i,j,k,h:byte;
f:text;
Begin
for i:=1 to n-2 do
begin
for h:=i+2 to n-1 do
begin
k:=0;
for j:= i to h do
begin
inc(k);
b[k]:=a[j];
end;
b[k+1]:=b[1];
Trang 5s1:=0;
for j:=1 to k do
s1:=s1+(b[j+1].x-b[j].x)*(b[j+1].y+b[j].y);
s1:=abs(s1)/2;
if del>abs(2*s1-s0) then
begin
vt1:=i;
vt2:=j;
del:=abs(2*s1-s0);
end;
end;
end;
assign(f,'dagiac.out');
rewrite(f);
write(f,vt1,' ',vt2);
close(f);
End;
begin
init;
resolve;
end.
Bài tập Tứ giác bao n điểm (mô phỏng đề thi olympic Sinh viên khối
không chuyên 1999).
Cho n điểm có toạ độ (xi , yi), i = 1, 2 , , n với n > 4 Lập chương trình tìm
4 điểm sao cho 4 điểm này tạo thành một tứ giác có diện tích lớn nhất