📜  门|门CS 2012 |问题 14(1)

📅  最后修改于: 2023-12-03 15:42:22.834000             🧑  作者: Mango

门|门CS 2012 |问题 14

这道题目是一个经典的计算几何问题,需要使用一定的数学知识和编程技巧来解决。下面我们一步步来介绍如何解决这道问题。

问题描述

有 $n$ 个门和 $m$ 个人($ n,m \leq 10^5 $),每个门是一条线段,人是一个点,问每个人在哪个门内。

思路分析

首先我们可以把每个门看做一个线段 $ (x_1,y_1) \rightarrow (x_2,y_2) $,每个人看做一个点 $ (x,y) $。然后我们可以使用计算几何的知识来判断一个点是否在一个线段内。具体方法是通过向量叉积的符号来判断。

假设一个点 $ P(x_0,y_0) $ 和线段 $ L_1((x_1,y_1),(x_2,y_2)) $,则可以用向量叉积来判断点 $ P $ 是否在线段 $ L_1 $ 上方或下方:

$$ \operatorname{Cross}(\overrightarrow{L_1},\overrightarrow{P-L_1}) = (x_2 - x_1)(y_0 - y_1) - (y_2 - y_1)(x_0 - x_1) $$

其中 $ \overrightarrow{L_1} $ 表示 $ L_1 $ 的方向向量,$ \overrightarrow{P-L_1} $ 表示从 $ L_1 $ 的起点 $ (x_1,y_1) $ 到点 $ P(x_0,y_0) $ 的向量。

如果 $ \operatorname{Cross}(\overrightarrow{L_1},\overrightarrow{P-L_1}) > 0 $,则 $ P $ 在 $ L_1 $ 上方;如果 $ \operatorname{Cross}(\overrightarrow{L_1},\overrightarrow{P-L_1}) < 0 $,则 $ P $ 在 $ L_1 $ 下方;如果 $ \operatorname{Cross}(\overrightarrow{L_1},\overrightarrow{P-L_1}) = 0 $,则 $ P $ 在 $ L_1 $ 上。

这个方法可以用来判断每个人在哪个门内。

代码实现

我们可以用 C++ 代码来实现上述方法:

#include <iostream>
using namespace std;

struct Point {
    double x, y;
};

struct Segment {
    Point p1, p2;
};

double Cross(Point A, Point B, Point C) {
    double x1 = B.x - A.x, y1 = B.y - A.y;
    double x2 = C.x - A.x, y2 = C.y - A.y;
    return x1 * y2 - x2 * y1;
}

int locate(Point P, Segment seg[], int n) {
    for (int i = 0; i < n; ++i) {
        if (Cross(seg[i].p1, seg[i].p2, P) > 0) return i + 1;
    }
    return -1;
}

int main() {
    int n, m;
    cin >> n >> m;

    Segment seg[n];
    for (int i = 0; i < n; ++i) {
        cin >> seg[i].p1.x >> seg[i].p1.y >> seg[i].p2.x >> seg[i].p2.y;
    }

    Point p[m];
    for (int i = 0; i < m; ++i) {
        cin >> p[i].x >> p[i].y;
    }

    for (int i = 0; i < m; ++i) {
        cout << locate(p[i], seg, n) << endl;
    }

    return 0;
}

上述代码中的 locate 函数实现了上文中的向量叉积判断方法,输入为点 $P$ 和所有的线段,输出为 $P$ 所在的线段编号。其中如果函数返回值为 $-1$ 则表示 $P$ 不在任何一个线段内。

结论

这样,我们就实现了一个简单的计算几何程序,可以用来解决问题。通过这样的练习,我们可以更好地掌握计算几何的技巧,进而开发更高级的程序。

以上是本人根据题目和自己的理解所写,如有错误,敬请指出。