题目大意:给定n个点。要求建造尽量少得铁路(从原点发射出的射线)。使得全部点到铁路的最短距离小于d。

解题思路:题目能够转化成区间选点问题,即以极角来表示铁轨。然后计算出每一个区间可行的极角范围,进行区间选点。

注意:(1)假设点到原点的距离dis<=d的话。不进行考虑,也无法推断。由于没有说直角边大于等于斜边的。

(2)区间有可能在二三象限时重叠,我的处理方法是每次枚举起始点,进行n次选点问题。

(3)由于每次都将区间i的左右区间+2pi后放到最后。忘记考虑s[i].r+2pi 有可能小于 s[m-1].r的情况,所以一直WA。

处理。在初始化区间时,将右区间大于pi的统一左右区间减掉2pi。

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

double pi = acos(-1);
int cnt;

struct Point {
    double l, r;
    bool operator < (Point a) const {
        return r < a.r;
    }
} A[500];

double cal(double x, double y) {
    return sqrt(x*x + y*y);
}

int solve() {
    sort(A, A + cnt);
    for (int i = 0; i < cnt; i++) {
        A[i + cnt].l = A[i].l + 2 * pi;
        A[i + cnt].r = A[i].r + 2 * pi;
    }

    int ans = cnt;
    for (int i = 0; i < cnt; i++) {
        double val = A[i].r;
        int tmp = 1;
        for (int j = i + 1; j < cnt + i; j++) if (A[j].l > val + 1e-9) {
            val = A[j].r;
            tmp++;
        }
        ans = min(ans, tmp);
    }

    return ans;
}

int main() {
    int N;
    scanf("%d", &N);
    while (N--) {
        int n;
        double d, x, y;
        scanf("%d%lf", &n, &d);
        cnt = 0;
        for (int i = 0; i < n; i++) {
            scanf("%lf%lf", &x, &y);
            if (cal(x, y) <= d) continue;
            double angle = atan2(y, x);
            double range = asin(d / cal(x, y));
            A[cnt].l = angle - range;
            A[cnt++].r = angle + range; 
            if (A[cnt-1].r <= pi) continue;
            A[cnt-1].r -= 2 * pi; 
            A[cnt-1].l -= 2 * pi;
        }

        printf("%d\n", solve());
    }
    return 0;
}