$\(Ax + By + C = 0\)$
Trong đó:
- Vectơ pháp tuyến (vuông góc với đường thẳng): \(\vec{n} = (A, B)\) (với \(A^2 + B^2 > 0\)).
- Vectơ chỉ phương (song song với đường thẳng): \(\vec{u} = (-B, A)\).
$\(y = kx + b\)$
Trong đó \(k\) là hệ số góc (độ dốc), \(b\) là tung độ gốc (giao điểm với trục \(Oy\)). Dạng này không biểu diễn được đường thẳng thẳng đứng song song với trục \(Oy\) (khi \(B = 0\) ở dạng tổng quát).
- Chuyển sang dạng tổng quát: \(kx - y + b = 0 \implies A = k, B = -1, C = b\).
$\(\begin{cases} x = x_0 + t \cdot u_x \\ y = y_0 + t \cdot u_y \end{cases}\)$
Trong đó \(P_0(x_0, y_0)\) là một điểm thuộc đường thẳng, \(\vec{u} = (u_x, u_y)\) là vectơ chỉ phương, và \(t \in \mathbb{R}\) là tham số tự do.
1.4 Cách dựng phương trình đường thẳng từ dữ kiện đầu vào¶
Đường thẳng đi qua 2 điểm \(P(x_1, y_1)\) và \(Q(x_2, y_2)\)¶
Vectơ chỉ phương là \(\vec{PQ} = (x_2 - x_1, y_2 - y_1)\). Do đó, vectơ pháp tuyến là \(\vec{n} = (y_1 - y_2, x_2 - x_1)\).
Thay điểm \(P\) vào phương trình tổng quát, ta thu được hệ số tự do \(C\):
$\(A = y_1 - y_2, \quad B = x_2 - x_1, \quad C = x_1 y_2 - x_2 y_1\)$
#include<bits/stdc++.h>usingnamespacestd;structPoint{doublex,y;};structLine{doubleA,B,C;// Ax + By + C = 0};// Dựng đường thẳng đi qua 2 điểmLinelineFromPoints(PointP,PointQ){doubleA=Q.y-P.y;doubleB=P.x-Q.x;doubleC=P.y*Q.x-P.x*Q.y;return{A,B,C};}// Dựng đường thẳng từ 1 điểm và vectơ pháp tuyến nLinelineFromPointNormal(PointP,Pointn){return{n.x,n.y,-n.x*P.x-n.y*P.y};}
Cho điểm \(P(x_0, y_0)\) và đường thẳng \(L: Ax + By + C = 0\). Khoảng cách hình học ngắn nhất từ \(P\) đến \(L\) được tính bằng công thức:
$\(d = \frac{|A x_0 + B y_0 + C|}{\sqrt{A^2 + B^2}}\)$
Để tìm điểm đối xứng \(P'\) của điểm \(P(x_0, y_0)\) qua đường thẳng \(L: Ax + By + C = 0\):
1. Hình chiếu vuông góc \(H(x_H, y_H)\) của \(P\) lên \(L\) lệch một lượng tỉ lệ với vectơ pháp tuyến \(\vec{n} = (A, B)\):
$\(H = P - t \cdot \vec{n}, \quad \text{với } t = \frac{A x_0 + B y_0 + C}{A^2 + B^2}\)$
2. Điểm đối xứng \(P'\) thỏa mãn \(H\) là trung điểm của \(PP'\):
$\(P' = 2H - P = P - 2 \cdot t \cdot \vec{n}\)$
$\(x_{P'} = x_0 - \frac{2A(A x_0 + B y_0 + C)}{A^2 + B^2}\)$
$\(y_{P'} = y_0 - \frac{2B(A x_0 + B y_0 + C)}{A^2 + B^2}\)$
// Khoảng cách từ điểm đến đường thẳngdoublepointToLine(PointP,LineL){returnabs(L.A*P.x+L.B*P.y+L.C)/hypot(L.A,L.B);}// Tìm điểm đối xứng qua đường thẳngPointreflectPoint(PointP,LineL){doubled=(L.A*P.x+L.B*P.y+L.C)/(L.A*L.A+L.B*L.B);return{P.x-2.0*L.A*d,P.y-2.0*L.B*d};}
Cho hai đường thẳng \(L_1: A_1 x + B_1 y + C_1 = 0\) và \(L_2: A_2 x + B_2 y + C_2 = 0\).
3.1 Phân tích điều kiện giao nhau (Định thức Cramer)¶
Hệ phương trình xác định giao điểm:
$\(\begin{cases} A_1 x + B_1 y = -C_1 \\ A_2 x + B_2 y = -C_2 \end{cases}\)$
Ta tính các định thức:
$\(D = A_1 B_2 - A_2 B_1, \quad D_x = B_1 C_2 - B_2 C_1, \quad D_y = C_1 A_2 - C_2 A_1\)$
\(D \neq 0\): Hai đường thẳng cắt nhau tại \(1\) điểm duy nhất:
$\(x = \frac{D_x}{D}, \quad y = \frac{D_y}{D}\)$
\(D = 0\):
Nếu \(D_x = 0\) (hoặc \(D_y = 0\)): Hai đường thẳng trùng nhau (vô số giao điểm).
Nếu \(D_x \neq 0\) (hoặc \(D_y \neq 0\)): Hai đường thẳng song song (không có giao điểm).
// Trả về giao điểm, nếu song song hoặc trùng trả về điểm vô cùng {1e18, 1e18}PointlineIntersection(LineL1,LineL2){doubledet=L1.A*L2.B-L2.A*L1.B;if(abs(det)<1e-9){return{1e18,1e18};}doublex=(L1.B*L2.C-L2.B*L1.C)/det;doubley=(L1.C*L2.A-L2.C*L1.A)/det;return{x,y};}
Bài toán: Cho đoạn thẳng \(AB\) và đoạn thẳng \(CD\). Hãy kiểm tra xem hai đoạn thẳng này có cắt nhau không, và tìm tọa độ giao điểm nếu có.
4.1 Thuật toán sử dụng Tích có hướng (Cross Product)¶
Ta định nghĩa phép tính tích có hướng của hai vectơ \(\vec{u}\) và \(\vec{v}\):
$\(\vec{u} \times \vec{v} = u_x v_y - u_y v_x\)$
Về mặt hình học, tích có hướng cho biết hướng quay của vectơ.
Hai đoạn thẳng \(AB\) và \(CD\) giao nhau khi và chỉ khi:
1. Hai điểm \(C\) và \(D\) nằm về hai phía khác nhau đối với đường thẳng chứa đoạn \(AB\).
2. Hai điểm \(A\) và \(B\) nằm về hai phía khác nhau đối với đường thẳng chứa đoạn \(CD\).
Lưu ý trường hợp đặc biệt: Khi tích có hướng bằng \(0\), tức là điểm nằm thẳng hàng với đoạn thẳng, ta cần dùng hàm on_segment để kiểm tra điểm đó có thực sự nằm đè lên đoạn thẳng kia hay không.
5. Khoảng cách ngắn nhất giữa các đối tượng hình học¶
5.1 Khoảng cách từ điểm \(P\) đến đoạn thẳng \(AB\)¶
Để tính khoảng cách ngắn nhất từ \(P\) đến đoạn thẳng \(AB\):
1. Tìm hình chiếu vuông góc \(H\) của \(P\) trên đường thẳng \(AB\).
2. Nếu hình chiếu \(H\) nằm trong đoạn \(AB\) (tương đương góc \(\angle PAB\) và \(\angle PBA\) đều nhọn), khoảng cách cần tìm là đoạn vuông góc \(PH\).
3. Nếu \(H\) nằm ngoài đoạn \(AB\), khoảng cách ngắn nhất là khoảng cách từ \(P\) tới đầu mút gần hơn (tức là \(\min(PA, PB)\)).
doublepointToSegment(PointP,PointA,PointB){doubled2=(B.x-A.x)*(B.x-A.x)+(B.y-A.y)*(B.y-A.y);if(d2<1e-9){returnhypot(P.x-A.x,P.y-A.y);// A và B trùng nhau}// Tính tỷ lệ chiếu tdoublet=((P.x-A.x)*(B.x-A.x)+(P.y-A.y)*(B.y-A.y))/d2;t=max(0.0,min(1.0,t));// Giới hạn t trong đoạn [0, 1] để hình chiếu nằm trên đoạn thẳngPointproj={A.x+t*(B.x-A.x),A.y+t*(B.y-A.y)};returnhypot(P.x-proj.x,P.y-proj.y);}
6. Diện tích đa giác (Công thức Shoelace / Gauss)¶
Bài toán: Cho một đa giác gồm \(n\) đỉnh được liệt kê theo thứ tự ngược chiều kim đồng hồ (hoặc cùng chiều): \((x_1, y_1), (x_2, y_2), \dots, (x_n, y_n)\). Hãy tính diện tích bề mặt của đa giác đó.
Đề bài: Cho hai đường thẳng \(L_1: A_1 x + B_1 y + C_1 = 0\) và \(L_2: A_2 x + B_2 y + C_2 = 0\). Tìm điểm giao của hai đường thẳng, hoặc in ra PARALLEL (song song) hoặc IDENTICAL (trùng nhau).
Độ khó: ★★☆
Lời giải
Sử dụng phương pháp Cramer để tính định thức và kiểm tra các điều kiện.
#include<bits/stdc++.h>usingnamespacestd;intmain(){doubleA1,B1,C1,A2,B2,C2;if(cin>>A1>>B1>>C1>>A2>>B2>>C2){doubledet=A1*B2-A2*B1;if(abs(det)<1e-9){// Kiểm tra tỷ lệ hệ số tự doif(abs(A1*C2-A2*C1)<1e-9&&abs(B1*C2-B2*C1)<1e-9){cout<<"IDENTICAL\n";}else{cout<<"PARALLEL\n";}}else{doublex=(B1*C2-B2*C1)/det;doubley=(C1*A2-C2*A1)/det;cout<<fixed<<setprecision(3)<<x<<" "<<y<<"\n";}}return0;}
importsysdefmain():input=sys.stdin.readdata=input().split()ifnotdata:returnA1,B1,C1,A2,B2,C2=map(float,data)det=A1*B2-A2*B1ifabs(det)<1e-9:# Kiểm tra trùng nhauifabs(A1*C2-A2*C1)<1e-9andabs(B1*C2-B2*C1)<1e-9:print("IDENTICAL")else:print("PARALLEL")else:x=(B1*C2-B2*C1)/dety=(C1*A2-C2*A1)/detprint(f"{x:.3f}{y:.3f}")if__name__=='__main__':main()
Đề bài: Cho hai đoạn thẳng \(AB\) và \(CD\) được xác định bởi tọa độ các đầu mút. Hãy tính khoảng cách ngắn nhất giữa hai đoạn thẳng này.
Độ khó: ★★★☆
Lời giải
Kiểm tra xem hai đoạn thẳng có cắt nhau không.
- Nếu cắt nhau, khoảng cách bằng \(0.0\).
- Nếu không cắt nhau, khoảng cách ngắn nhất chính là giá trị nhỏ nhất của các khoảng cách từ đầu mút của đoạn này tới đoạn thẳng kia: \(\min(\text{dist}(A, CD), \text{dist}(B, CD), \text{dist}(C, AB), \text{dist}(D, AB))\).