HDU7146. Laser (2022杭电多校第1场I题)

HDU7146. Laser (2022杭电多校第1场I题)

题意

给出二维平面上有 \(n\) 个点的坐标,第 \(i\) 个点的坐标为 \((x_i, y_i)\),现要在二维平面上找一点 \((x, y)\),使得以该点为中心的米字型射线能够覆盖所有的 \(n\) 个点。输出是否可以找到这样的点。

米字型射线的定义:从中心向0,45,90,135,180,225,270,315度方向角的射线。

分析

先考察第 \(1\) 个点与其他所有点的关系,如果所有点都满足米字型射线所包含的斜率(\(0,-1,1,\infty\)),则已经找到答案,输出 YES

如果存在 \(1\) 个点与第 \(1\) 个点的关系不满足米字型射线,则找到了一对斜率不是 \(0,-1,1\) 的点对,容易发现,若要构造一个米字型射线,使得这两个点被覆盖,只有有限个中心可以作为答案。

经过缜密的计算,共有 \(12\) 个点,满足条件,不妨设要被覆盖的 \(2\) 个点为 \((x_1,y_1),(x_2,y_2)\),则 \(12\) 个可能的中心为:

\[ (x_2,y_1)\\ (x_1,y_2)\\ \left(\frac{y_2-y_1+x_1+x_2}{2},\frac{x_2-x_1+y_1+y_2}{2}\right)\\ \left(\frac{y_1-y_2+x_1+x_2}{2},\frac{x_1-x_2+y_1+y_2}{2}\right)\\ \left(x_1-y_1+y_2,y_2\right)\\ \left(x_2-y_2+y_1,y_1\right)\\ \left(x_2-y_1+y_2,y_1\right)\\ \left(x_1-y_2+y_1,y_2\right)\\ \left(x_2, x_1-x_2+y_1\right)\\ \left(x_1, x_2-x_1+y_2\right)\\ \left(x_1, x_1-x_2+y_2\right)\\ \left(x_2, x_2-x_1+y_1\right)\\ \]

我们可以分别以 \(O(n)\) 的时间复杂度检验这 \(12\) 个中心(方法和一开始考察第 \(1\) 个点与其他所有点的关系相同),如果这 \(12\) 个中心没有一个满足条件,输出 NO,否则输出 YES

时间复杂度为 \(O(12n)\)

代码

#include <iostream>
using namespace std;
typedef long long Lint;
const int maxn = 5e5 + 10;
Lint x[maxn], y[maxn];
int n;
bool check(Lint x1, Lint y1, Lint x2, Lint y2) {
    if (x1 == x2)
        return true;
    if (y1 == y2)
        return true;
    if (abs(x1 - x2) == abs(y1 - y2))
        return true;
    return false;
}
bool is_ok(Lint xx, Lint yy) {
    for (int i = 1; i <= n; i++) {
        if (!check(xx, yy, x[i], y[i])) {
            return false;
        }
    }
    return true;
}
void solve() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x[i] >> y[i];
        x[i] <<= 1;
        y[i] <<= 1;
    }
    int pos = 0;
    for (int i = 2; i <= n; i++) {
        if (!check(x[1], y[1], x[i], y[i])) {
            pos = i;
            break;
        }
    }
    if (pos == 0) {
        cout << "YES\n";
        return;
    }
    pair<Lint, Lint> V[] = {{x[pos], y[1]},
                            {x[1], y[pos]},
                            {(y[pos] - y[1] + x[1] + x[pos]) / 2, (x[pos] - x[1] + y[1] + y[pos]) / 2},
                            {(y[1] - y[pos] + x[1] + x[pos]) / 2, (x[1] - x[pos] + y[1] + y[pos]) / 2},
                            {x[1] - y[1] + y[pos], y[pos]},
                            {x[pos] - y[pos] + y[1], y[1]},
                            {x[pos] - y[1] + y[pos], y[1]},
                            {x[1] - y[pos] + y[1], y[pos]},
                            {x[pos], x[1] - x[pos] + y[1]},
                            {x[1], x[pos] - x[1] + y[pos]},
                            {x[1], x[1] - x[pos] + y[pos]},
                            {x[pos], x[pos] - x[1] + y[1]}};
    for (auto it : V) {
        Lint x = it.first, y = it.second;
        if (is_ok(x, y)) {
            cout << "YES\n";
            return;
        }
    }
    cout << "NO\n";
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T;
    cin >> T;
    while (T--)
        solve();
    return 0;
}
posted @ 2022-07-19 20:13  聆竹听风  阅读(218)  评论(0)    收藏  举报