zoukankan      html  css  js  c++  java
  • UPC11456 视线(计算几何)

    视线

    时间限制: 1 Sec 内存限制: 128 MB
    提交: 21 解决: 2

    [提交] [状态] [命题人:admin]

    题目描述

    二维平面上,原点处有一个半径为R的圆。平面上有N个点,保证没有点在圆上或圆内,保证任意两个点不与圆相切,求互相可以看见的点的对数。
    看见:对于两个点(x1,y1)和(x2,y2),他们的线段与圆没有交点。
    计算对数时,(a,b)和(b,a)视为相同,且(a,a)不算点对。

    输入

    第一行,两个整数 N,R。
    第 2 ~ N+1行,每行两个整数,表示点的坐标。

    输出

    一行,一个整数,表示能互相看见的点的对数。

    样例输入

    4 5
    0 10
    0 -10
    10 0
    -10 0
    

    样例输出

    4
    

    提示

    对于40%的数据,N≤1000。
    对于100%的数据,N≤50000。
    点的坐标为[−106,106]内的整数。
    R的取值为[1,106]内的整数。

    只能说昨天训练的时候复杂度分析对了…… 但是没想出来具体是要怎么sort

    如上图所示,两个点互相可见有两种情况。

    从A和B分别向圆做切线,会产生四个切点。

    • 第一种情况中B的一个切点在A的两个切点之间,A的一个切点在B的两个切点
      之间。

    • 第二种情况A的两个切点在B的两个切点之间。

      所以把所有的切点求出来并排序,然后对于每一个点利用二分求出它两个切点之间有多少个切点(记为(a_i)), (ans = frac{sum_{0}^{n-1} a_i}{2})

    #include "bits/stdc++.h"
    
    using namespace std;
    typedef long long ll;
    const int mod = 1e9 + 7;
    const int maxn = 1e5 + 100;
    const int inf = 0x3f3f3f3f;
    const double pi = acos(-1);
    const double esp = 1e-9;
    
    
    struct point {
        double x, y;
    } a[maxn];
    
    struct node {
        double begin, end;
    } e[maxn];
    
    vector<double> s;
    
    int dtoicmp(double a) {
        if (fabs(a) < esp) return 0;
        return a > 0 ? 1 : -1;
    }
    
    int main() {
       // freopen("in.txt", "r", stdin);
        int n;
        double r;
        cin >> n >> r;
        for (int i = 0; i < n; i++) {
            cin >> a[i].x >> a[i].y;
            double len = sqrt(a[i].x * a[i].x + a[i].y * a[i].y);
            double r1 = acos(r / len);
            double r2 = atan2(a[i].y, a[i].x);
            e[i] = {r2 - r1 + 2 * pi, r2 + r1 + 2 * pi};
            if (dtoicmp(e[i].begin - 2 * pi) >= 0) e[i].begin -= 2 * pi;
            if (dtoicmp(e[i].end - 2 * pi) >= 0) e[i].end -= 2 * pi;
            if (dtoicmp(e[i].end - e[i].begin) <= 0) swap(e[i].end, e[i].begin);
            s.push_back(e[i].begin);
            s.push_back(e[i].end);
        }
        long long ans = 0;
        sort(s.begin(), s.end());
    
        long long from, to;
        for (int i = 0; i < n; i++) {
            from = lower_bound(s.begin(), s.end(), e[i].begin) - s.begin();
            to = lower_bound(s.begin(), s.end(), e[i].end) - s.begin();
            if (dtoicmp(e[i].end - e[i].begin - pi) >= 0)
                ans = ans + 2 * n - (to - from - 1)-2;
            else
                ans = ans + to - from - 1;
        }
        cout << ans / 2 << endl;
        return 0;
    }
    
  • 相关阅读:
    BMC手册—具体工作内容。——在Agent中修改配置文件添加ping监控
    BMC手册—具体工作内容。——在PATROL Central控制台中添加Linux监控oracle的添加
    jetbrains 系列博客https://zhile.io/
    NavicatPremium15破解方法
    fastjson转换json字符串key的首字母小写变大写的解决办法
    Linux系统时间同步方法小结
    java同步/设置Linux系统时间
    Java代码获取NTP服务器时间
    IDEA2019 3.3 IDEA缓存和浏览缓存清除和设置
    一张图彻底搞懂MySQL的 explain
  • 原文地址:https://www.cnblogs.com/albert-biu/p/10907996.html
Copyright © 2011-2022 走看看