uva10691 几何水题

来源:互联网 发布:淘宝店优惠删链接 编辑:程序博客网 时间:2024/04/29 16:53
/*************************************************************题意:给你一些点,要做一些从原点出发的射线使这些点到最近的射线的距离都不超过 d ,求最少需要做多少根射线思路:算出每个点到与它距离不大于 d 的射线的角度的区间,然后就是区间选点的问题了,贪心由于这是一个圈,所以要从每个开始都算一下,一个简单的方法就是把它拓展一倍**************************************************************/#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>using namespace std;int pn;const double PI = acos(-1);const double eps = 1e-9;int cmp(double x){    if(x < -eps) return -1;    if(x > eps) return 1;    return 0;}struct Point{    double l, r;    Point(): l(0.0), r(0.0){}}p[777];bool radCmp(const Point &a, const Point &b){return a.r < b.r;}int solve(){    double pre;    int ans = pn, t;sort(p, p + pn, radCmp);for (int i = 0; i < pn; i++) {p[i + pn].l = p[i].l + 2 * PI;p[i + pn].r = p[i].r + 2 * PI;}    for(int i = 0; i < pn; i++)    {        int tmp = 1;        pre = p[i].r;        for(t = i + 1; t - i < pn; t++)        {            if(cmp(p[t].l - pre) > 0)            {                tmp++;                pre = p[t].r;            }        }        ans = min(ans, tmp);    }    return ans;}int main(){    int T;    scanf("%d", &T);    while(T--)    {        int n, d, i, x, y;        double tmp;        scanf("%d %d", &n, &d);        pn = 0;        for(i = 0; i < n; i++)        {            scanf("%d %d", &x, &y);            int ds2 = x * x + y * y;            if(ds2 <= d * d) continue;            p[pn].l = p[pn].r = atan2(1.0 * y, 1.0 * x);            tmp = asin(1.0 * d / sqrt(1.0 * ds2));            p[pn].l -= tmp;            p[pn].r += tmp;            if(cmp(p[pn].r - PI) > 0)            {                p[pn].r -= 2 * PI;                p[pn].l -= 2 * PI;            }            pn++;        }        printf("%d\n", solve());    }    return 0;}

0 0
原创粉丝点击