• 题解 LA4064


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

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

    我们从反面出发,统计钝角三角形的个数,也就是钝角的个数(为什么)。那么使用与那道题相同的做法,枚举每个点作为原点,算出其他点到原点的极角,排序。然后枚举每个点 (A) 用两个指针维护 ([ang_A+frac{pi}{2},ang_A+pi]) 中的所有点的个数,这就是钝角的个数。由于满足单调性所以不会增加复杂度,总体复杂度为 (O(n^2log 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:
    There are %lld sites for making valid tracks
    ", ++t, C(n, 3) - ans);
    	}
    }
    
  • 相关阅读:
    数学工具WZgrapher
    零线和地线的区别,示波器如何测量市电?
    使用直流稳压电源时的注意事项!
    中文全角和半角输入有什么区别?
    ThinkingRock:使用方法
    2014记首
    如何使用Excel绘制甘特图
    AStyle代码格式工具在source insight中的使用
    STM32F103系列命名规则
    上市公司行情查询站点
  • 原文地址:https://www.cnblogs.com/whx1003/p/12297626.html
Copyright © 2020-2023  润新知