Hướng dẫn giải của Khoảng cách trong không gian


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Lời giải này đang bị ẩn cho đến khi bạn chọn mở ra.

Chúng tôi khuyên bạn nên tự thử giải bài trước. Việc mở lời giải có thể làm lộ mất ý tưởng chính trước khi bạn có cơ hội tự giải.

Bạn phải đăng nhập để mở lời giải này.

Đăng nhập

Tác giả: Hiếu Nguyễn, yourname, lqvinh13, TuongLau2025

Editorial for 3ddist: Khoảng cách trong không gian

Hiểu bài toán

Bài toán yêu cầu tính khoảng cách từ một điểm A đến đường thẳng đi qua hai điểm B và C trong không gian ba chiều. Với mỗi test case, ta nhập tọa độ của 3 điểm A, B, C và cần xuất ra khoảng cách từ A đến đường thẳng BC làm tròn đến 2 chữ số thập phân.

Các cách tiếp cận

Cách Công thức hình học qua diện tích tam giác
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    long T;
    cin >> T;

    cout << fixed << setprecision(2);

    while (T--) {
        double xa, ya, za;
        double xb, yb, zb;
        double xc, yc, zc;

        cin >> xa >> ya >> za;
        cin >> xb >> yb >> zb;
        cin >> xc >> yc >> zc;

        double bax = xa - xb;
        double bay = ya - yb;
        double baz = za - zb;

        double bcx = xc - xb;
        double bcy = yc - yb;
        double bcz = zc - zb;

        double cx = bay * bcz - baz * bcy;
        double cy = baz * bcx - bax * bcz;
        double cz = bax * bcy - bay * bcx;

        double cross_len = sqrt(cx*cx + cy*cy + cz*cz);
        double bc_len = sqrt(bcx*bcx + bcy*bcy + bcz*bcz);

        double distance = cross_len / bc_len;
        cout << distance << endl;
    }
    return 0;
}
  • Time Complexity: O(1) cho mỗi test case
  • Space Complexity: O(1)

Cách này dựa trên công thức diện tích: Diện tích tam giác ABC = 1/2 * |AB × AC| (vectors) hoặc 1/2 * |BA × BC|. Khoảng cách từ A đến đường thẳng BC là chiều cao tương ứng: h = (2 * diện tích) / (độ dài cạnh BC) = |BA × BC| / |BC|. Ta tính vector BA (từ B đến A) và BC (từ B đến C), tính vector tích (cross product) của chúng, lấy độ dài của vector tích chia cho độ dài của BC.

Cách Công thức hình học qua diện tích tam giác (biến thể)
#include <bits/stdc++.h>
using namespace std;

struct Point {
    double x, y, z;
};

double distance(Point A, Point B, Point C) {
    Point AB = {B.x - A.x, B.y - A.y, B.z - A.z};
    Point AC = {C.x - A.x, C.y - A.y, C.z - A.z};
    Point BC = {C.x - B.x, C.y - B.y, C.z - B.z};

    double cross_x = AB.y * AC.z - AB.z * AC.y;
    double cross_y = AB.z * AC.x - AB.x * AC.z;
    double cross_z = AB.x * AC.y - AB.y * AC.x;

    double area = sqrt(cross_x * cross_x + cross_y * cross_y + cross_z * cross_z);
    double length_BC = sqrt(BC.x * BC.x + BC.y * BC.y + BC.z * BC.z);

    return area / length_BC;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int T;
    cin >> T;

    cout << fixed << setprecision(2);

    while (T--) {
        Point A, B, C;
        cin >> A.x >> A.y >> A.z;
        cin >> B.x >> B.y >> B.z;
        cin >> C.x >> C.y >> C.z;

        cout << distance(A, B, C) << endl;
    }
    return 0;
}
  • Time Complexity: O(1) cho mỗi test case
  • Space Complexity: O(1)

Biến thể khác của cách 1. Thay vì tính từ B, ta tính vector AB và AC (từ A), tính tích chéo AB × AC. Diện tích tam giác ABC bằng 1/2 độ dài vector tích chéo. Khoảng cách từ A đến BC là chiều cao = (2 * diện tích) / |BC| = |AB × AC| / |BC|. Phương pháp này cũng sử dụng phép tích chéo nhưng định nghĩa vector khác.

Cách Tối ưu với số nguyên
#include <bits/stdc++.h>
using namespace std;

int main(){
    int  t;
    cin >> t;

    while(t--){
        long long ax, bx, cx, ay, by, cy, az, bz, cz;
        cin  >> ax >> ay >> az >> bx >> by >> bz >>  cx >> cy >> cz;

        long long bax = bx - ax, bay = by - ay, baz = bz - az; // vector BA
        long long bcx = bx - cx, bcy = by - cy, bcz = bz - cz; // Vector BC

        double len_bcx = sqrt(1.0*bcx*bcx + 1.0*bcy*bcy + 1.0*bcz*bcz);
        long long tch_x = bay*bcz - baz*bcy, tch_y = baz*bcx - bax*bcz, tch_z = bax*bcy - bcx*bay;
        double len_tch = sqrt(1.0*tch_x*tch_x +  1.0*tch_y*tch_y + 1.0*tch_z*tch_z);

        cout << setprecision(2) << fixed << len_tch / len_bcx << endl;
    }

    return 0;
}
  • Time Complexity: O(1) cho mỗi test case
  • Space Complexity: O(1)

Giải pháp này sử dụng số nguyên (long long) cho các phép tính vector để tránh sai số tràn số sớm nếu tọa độ lớn, và chỉ chuyển sang kiểu double khi tính căn bậc hai và chia. Tuy nhiên, về cơ bản vẫn là cách tính diện tích tam giác qua tích chéo. Vector BA được tính từ B đến A, vector BC từ B đến C. Tích chéo BA × BC cho vector pháp tuyến của mặt phẳng chứa tam giác ABC.

Phân tích độ phức tạp

Cách tiếp cận Time Space Tên
1 O(1) cho mỗi test case O(1) Công thức hình học qua diện tích tam giác
2 O(1) cho mỗi test case O(1) Công thức hình học qua diện tích tam giác (biến thể)
3 O(1) cho mỗi test case O(1) Tối ưu với số nguyên

Bài học kinh nghiệm

  • Khoảng cách từ điểm A đến đường thẳng BC có thể tính bằng chiều cao của tam giác ABC: h = (Diện tích * 2) / (Độ dài cạnh BC).
  • Diện tích tam giác ABC trong không gian có thể tính bằng nửa độ dài của vector tích chéo (cross product) của hai cạnh vectơAB và AC hoặc BA và BC.
  • Công thức: Khoảng cách = |BA × BC| / |BC| (hoặc |AB × AC| / |BC|).

Lỗi thường gặp

  • Lỗi sai trong tính toán tích chéo (cross product): Các thành phần x, y, z của vector tích chéo phải được tính đúng quy tắc (y1z2 - z1y2, z1x2 - x1z2, x1y2 - y1x2).
  • Sai số làm tròn: Cần in kết quả làm tròn chính xác đến 2 chữ số thập phân. Trong C++, sử dụng fixedsetprecision(2).
  • Lỗi type overflow: Nếu dùng số nguyên để tính bình phương trực tiếp, có thể bị tràn số khi tọa độ lớn. Nên dùng long long cho các phép nhân trừ cộng trừ trước khi lấy căn, hoặc dùng double ngay từ đầu.

Bình luận

Please read the guidelines before commenting.


Không có bình luận tại thời điểm này.