题解 LA4064

题目大意 多组数据,每组数据给定一个正整数 \(n(n\leq 1200)\) 和平面内 \(n\) 个点的坐标。要求输出所有锐角和直角三角形的个数。

分析 这道题和 UVa 11529 特别像,就连数据范围也一样。

我们从反面出发,统计钝角三角形的个数,也就是钝角的个数(为什么)。那么使用与那道题相同的做法,枚举每个点作为原点,算出其他点到原点的极角,排序。然后枚举每个点 \(A\) 用两个指针维护 \([ang_A+\frac{\pi}{2},ang_A+\pi]\) 中的所有点的个数,这就是钝角的个数。由于满足单调性所以不会增加复杂度,总体复杂度为 \(O(n^2\log n)\)

注意精度问题,坐标最好存成浮点数,我因为这个 WA 了 \(3\) 次。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 1205;
const double PI = acos(-1.0), eps = 1E-10;

ll n, t, tot, now1, now2;
ll ans, cnt;
double ang[maxn * 2];
struct Point {
    double x, y;
} p[maxn];

ll C(ll n, ll m)
{
    if(n < m) return 0;
    
    ll res = 1;
    for(ll i = 1; i <= m; ++i)
        res = res * (n - i + 1) / i;
    return res;
}

ll count(int x)
{
    tot = 0, now1 = 1, now2 = 1, cnt = 0;   
    for(ll i = 1; i <= n; ++i) {
        if(i == x) continue;
        ang[++tot] = atan2(p[i].y - p[x].y, p[i].x - p[x].x);
        
        if(ang[tot] < 0) ang[tot] += 2 * PI;
        ang[tot + n - 1] = ang[tot] + 2 * PI;
    }
    
    sort(ang + 1, ang + tot * 2 + 1);
    
    for(ll i = 1; i <= tot; ++i) {
        while(ang[now1] - ang[i] <= PI * 0.5 - eps) ++now1;
        while(ang[now2] - ang[i] < PI) ++now2;
        cnt += now2 - now1;
    }
    
    return cnt;
}

int main()
{
    while(~scanf("%lld", &n) && n) {
        ans = 0;
        
        for(int i = 1; i <= n; ++i)
            scanf("%lf%lf", &p[i].x, &p[i].y);
        
        for(int i = 1; i <= n; ++i)
            ans += count(i);
            
        printf("Scenario %lld:\nThere are %lld sites for making valid tracks\n", ++t, C(n, 3) - ans);
    }
}

猜你喜欢

转载自www.cnblogs.com/whx1003/p/12297626.html
LA
今日推荐