Hình vuông cũng thú vị lắm chứ
Bùi Tứ Quý
Hẳn các bạn đã biết đến hình vuông, một tứ giác đặc biệt có 4 cạnh bằng nhau và 4 góc
bằng nhau (bằng 900), hình vuông là sự kết hợp hoàn hảo giữa hình chữ nhật và hình thoi.
Trong Tin học, cũng có rất nhiều bài toán thú vị về hình vuông. Chúng ta hãy cùng tìm
hiểu một trong số các bài toán ấy.
Trước tiên, chúng ta cùng xét bài toán:
Bài toán 1. Cho 4 điểm trên mặt phẳng. Hãy kiểm tra xem bốn điểm này có phải là đỉnh
của một hình vuông có các cạnh song song với trục toạ độ hay không.
Nhận xét 1a. Hình vuông là hình chữ nhật có 4 cạnh bằng nhau. Nhận xét 1b. Nếu xA =
xB, xC = xD, yA = yD và yB = yC thì ABCD là hình chữ nhật (có các cạnh song song với
trục toạ độ).
Bước 1. Bạn sắp xếp toạ độ 4 điểm theo thứ tự tăng dần theo hoành độ (trong hình, thứ tự
các điểm sau khi sắp xếp là A, B, D, C). Sau đó chúng ta kiểm tra nhận xét 1b. Nếu đúng
chúng ta qua bước 2, nếu sai ta ghi kết quả ‘SAI’. Bước 2. Tính độ dài AB, BD, CD, DA.
Nếu AB = BC = CD = DA thì ta ghi ‘DUNG’, nếu sai ta ghi ‘SAI’.
Như vậy chúng ta đã giải quyết xong bài toán 1. Tuy nhiên, nếu các cạnh hình vuông
không song song với trục toạ độ thì bài toán 1 sẽ trở thành bài toán như sau:
Bài toán 2. Cho 4 điểm trên mặt phẳng. Hãy kiểm tra xem bốn điểm này có thể là đỉnh của
1 hình vuông hay không?
Input: File KTHV.INP gồm 4 dòng là toạ độ 4 điểm ban đầu. Output: File KTHV.OUT
chứa số 1 (hoặc -1) nếu 4 điểm đó có thể (không thể) là 4 đỉnh một hình vuông.
Ví dụ:
Nếu giải theo cách thông thường, ta không những kiểm tra độ dài 4 cạnh mà phải kiểm tra
đến cả độ lớn 4 góc. Tôi đã nghĩ ra một giải thuật đơn giản hơn như sau:
Chúng ta cũng sắp xếp 4 điểm ban đầu theo thứ tự tăng dần theo hoành độ, ta được 4 điểm
đã sắp xếp theo thứ tự là A, B, D, C. Sau đó, chúng ta sẽ tạo ra 4 điểm mới là A’, B’, C’,
D’ sao cho xA’ = xB’ = min (các hoành độ của A, B, C, D) ; xC’ = xD’ = max (các hoành
độ của A, B, C, D); yA’ = yD’ = min (các tung độ của A, B, C, D); yB’ = yC’ = max (các
tung độ của A, B, C, D).
Bây giờ chúng ta kiểm tra giá trị k = (A’B’ = B’C’ = C’D’ = D’A’) and (AB = BC = CD =
DA). Nếu k = True thì ABCD là hình vuông, ngược lại thì ABCD không phải là hình
vuông.
Sau đây là chương trình của bài 2.
Program KiemTraHinhVuong;
Const fi = 'KTHV.INP';
fo = 'KTHV.OUT';
Type Point = Record
x,y:real;
End;
Var P : Array[1..8] of Point; {Các điểm A,B,D,C,A’,B’,C’,D’}
A : Array[1..8] of Real; {AB,BC,CD,DA,A’B’,B’C’,C’D’,D’A’}
i,j : byte;
f:text;
Function D(A,B:Point):real;
Begin
D:=sqrt(sqr(A.x-B.x)+sqr(A.y-B.y));
End;
Procedure DoiCho(Var A,B:Point);
Var k : Point;
Begin
k:=A; A:=B; B:=k;
End;
Procedure ReadInp;
Begin
Assign(f,fi); Reset(f);
For i:=1 to 4 do
Read(f,P[i].x,P[i].y);
Close(f);
End;
Procedure Solve;
Var minx,miny,maxx,maxy:real;
k:boolean;
Begin
For i:=1 to 4 do
For j:=i to 4 do
If P[i].x>P[j].x then DoiCho(P[i],P[j]);
minx:=P[1].x; miny:=P[1].y;
maxx:=P[1].x; maxy:=P[1].y;
For i:=2 to 4 do
Begin
If P[i].x
If P[i].y
If P[i].x>maxx then maxx:=P[i].x;
If P[i].y>maxy then maxy:=P[i].y;
End;
P[5].x:=minx; P[6].x:=minx;
P[7].x:=maxx; P[8].x:=maxx;
P[5].y:=miny; P[8].y:=miny;
P[6].y:=maxy; P[7].y:=maxy;
k:=false;
A[1]:=D(P[1],P[2]); A[2]:=D(P[2],P[4]);
A[3]:=D(P[4],P[3]); A[4]:=D(P[3],P[1]);
A[5]:=D(P[5],P[6]); A[6]:=D(P[6],P[7]);
A[7]:=D(P[7],P[8]); A[8]:=D(P[8],P[5]);
k:=(A[1]=A[2]) and (A[2]=A[3]) and (A[3]=A[4]);
k:= k and (A[5]=A[6]) and (A[6]=A[7]) and (A[7]=A[8]);
Assign(f,fo); Rewrite(f);
If k then Writeln(f,1) else Writeln(f,-1);
Close(f);
End;
Begin
ReadInp;
Solve;
End.
Bạn đọc có thể tự chứng minh thuật toán trên cho bài toán 2 là đúng. Nếu không thích, bạn
cũng có thể kiểm tra góc vuông bằng cách kiểm tra 4 tam giác ABC, BCD, CDA, DAB có
phải là 4 tam giác vuông lần lượt tại 4 đỉnh B, C, D, A hay không (bằng định lí Pythagore
đảo)...
Bài toán 3. Cho hai điểm ĂxA, yA) và B(xB, yB) không trùng nhau. Hãy tìm toạ độ các
điểm C, D, E, F sao cho ABCD và ABEF là các hình vuông.
Sau khi phân tích bài toán này, tôi được kết quả:
Nếu xA xB thì toạ độ 4 điểm C, D, E, F sẽ là:
xC = xB + (yB - yA) ; yC = yB – (xB – xA).
xD = xA + (yB - yA) ; yD = yA – (xB – xA).
xE = xB – (yB - yA) ; yE = yB + (xB – xA).
xF = xA – (yB - yA) ; yF = yA + (xB – xA).
Với xA > xB thì với tính toán như trên, ta sẽ được hai hình vuông ABDC, ABFE (không
đúng với đề), do đó chúng ta chỉ cần đảo toạ độ hai điểm C và D cho nhau, E và F cho
nhau.
Bài toán 3 là bài toán cho 2 đỉnh kề nhau, xác định 2 đỉnh còn lại của hình vuông. Sau đây
là bài toán 4, cho 2 đỉnh đối nhau, xác định 2 đỉnh còn lại của hình vuông.
Bài toán 4. Cho hai điểm A (xA, yA) và C(xC, yC) là hai đỉnh đối nhau của một hình
vuông. Hãy tìm toạ độ các điểm B và D sao cho ABCD là hình vuông.
Input : File HAIDINH.INP gồm 2 dòng là toạ độ 2 đỉnh A và C của hình vuông.
Output : File HAIDINH.OUT gồm 2 dòng là toạ độ 2 đỉnh B và D của hình vuông
(mỗi toạ độ trong file output chính xác đến chữ số thứ 4 sau dấu phẩy).
Ta có nhận xét: Hình vuông có hai đường chéo bằng nhau và vuông góc với nhau tại trung
điểm mỗi đường. Ta cần tìm trung điểm của AC, đó là điểm O có toạ độ:
Sau đó, chúng ta phân tích tiếp, được kết quả:
xB = xO + (yA – yO) ; yB = yO + (xO – xA)
xD = xO – (yA – yO) ; yD = yO – (xO – xA)
Sau đây là chương trình của bài 4.
Program Tim2Dinh;
Const fi = 'HAIDINH.INP';
fo = 'HAIDINH.OUT';
Type Point = Record
x,y:real;
End;
Var P:Array[1..5] of Point;
f:text;
Procedure ReadInp;
Begin
Assign(f,fi); Reset(f);
Read(f,P[1].x,P[1].y);
Read(f,P[2].x,P[2].y);
Close(f);
End;
Procedure Solve;
Begin
P[5].x:=(P[1].x+P[2].x)/2;
P[5].y:=(P[1].y+P[2].y)/2;
P[3].x:=P[5].x+(P[1].y-P[5].y);
P[3].y:=P[5].y+(P[5].x-P[1].x);
P[4].x:=P[5].x-(P[1].y-P[5].y);
P[4].y:=P[5].y-(P[5].x-P[1].x);
End;
Procedure WriteOut;
Begin