码迷,mamicode.com
首页 > 其他好文 > 详细

UVA - 10691 Subway

时间:2015-08-10 16:12:41      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:给定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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

UVA - 10691 Subway

标签:

原文地址:http://blog.csdn.net/kl28978113/article/details/47399583

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!