原问题即求平面内一点到目标点坐标均小于等于 RR

可以以每个敌人为圆心, RR 为半径作圆,交集即为解集(解集可以为空)。若解集不为空,则必然可以移动爆炸点到解集边缘,即圆两两之间的交点上。

枚举所有圆两两之间的交点,检验其是否在所有圆的圆内,只要存在一个满足条件的点,输出Y,否则输出N。

SPEC:n=1,特判,输出Y。

计算交点思路:

两点距离 DD 大于 RR 无解,重合不考虑(题目保证不重合)。

解析解法:先解出中垂线方程(过中点,斜率为(x1-x2)/(y2-y1)),联立它和其中一个圆,韦达解出两个交点。

几何解法:或已知斜率三角形,解出交点与中点的偏移量,然后取正偏、负偏两个交点。

STD

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>

using namespace std;
const double EPS = 1e-8;
struct Point {double x, y;};
double distSq(Point p1, Point p2) {
    return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);
}
double dist(Point p1, Point p2) {
    return sqrt(distSq(p1, p2));
}

void solve() {
    int n;
    double R;
    cin >> n >> R;
    
    vector<Point> enemies(n);
    for (int i = 0; i < n; i++) {
        cin >> enemies[i].x >> enemies[i].y;
    }

    if (n == 1) {
        cout << "Y" << endl;
        return;
    }

    double R2 = R * R; 
    bool possible = false;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            double d2 = distSq(enemies[i], enemies[j]);
            double d = sqrt(d2);
            if (d > 2.0 * R + EPS) continue;
            double midX = (enemies[i].x + enemies[j].x) / 2.0;
            double midY = (enemies[i].y + enemies[j].y) / 2.0;
            double h = sqrt(max(0.0, R * R - d2 / 4.0));
            double dx = (enemies[j].x - enemies[i].x);
            double dy = (enemies[j].y - enemies[i].y);
            
            
            Point c1, c2;
            c1.x = midX - dy * h / d;
            c1.y = midY + dx * h / d;
            
            c2.x = midX + dy * h / d;
            c2.y = midY - dx * h / d;

            bool ok1 = true;
            for (int k = 0; k < n; k++) {
                if (distSq(c1, enemies[k]) > R2 + EPS) {
                    ok1 = false;
                    break;
                }
            }
            if (ok1) {
                possible = true;
                break;
            }

            bool ok2 = true;
            for (int k = 0; k < n; k++) {
                if (distSq(c2, enemies[k]) > R2 + EPS) {
                    ok2 = false;
                    break;
                }
            }
            if (ok2) {
                possible = true;
                break;
            }
        }
        if (possible) break;
    }

    if (possible) cout << "Y" << endl;
    else cout << "N" << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	freopen("Strinova.in","r",stdin); 
	freopen("Strinova.out","w",stdout); 
    int t;
    if (cin >> t) {
        while (t--) {
            solve();
        }
    }
    return 0;
}

1 条评论

  • @ 2025-12-25 16:46:27

    这么简单的数学题放T4还是太迷惑人了。你说得对,但是卡拉比丘是一款二次元美少女射击游戏···

    • 1