• LOJ 2882「JOI Spring Camp 2014 Day4」两个人的星座 (极角排序)


    题目链接:https://loj.ac/p/2882

    极角排序:使用 (atan2(y,x))函数,返回点与原点的连线与 (x) 轴的夹角,范围是 ([-180,180]),可以加上 (pi),使得范围为 ([0,360])

    题解:
    若两个三角形不相交,则一定存在两条切线,使得两个三角形分别在切线的两端,
    于是枚举每个点,按极角序枚举切线,统计切线两侧不同颜色点的数量,计算即可,具体实现参考代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 3010;
    const double eps = 1e-8;
    const double pi = acos(-1.0);
    
    int n;
    int c[maxn];
    ll sum[3][maxn];
    ll ans = 0;
    
    struct Point{
    	int x, y, c;
    	double k;
    	
    	bool operator < (const Point &b) const {
    		return k < b.k;
    	}
    }a[maxn], b[maxn];
    
    Point operator + (Point a, Point b){ return (Point){a.x + b.x, a.y + b.y}; }
    Point operator - (Point a, Point b){ return (Point){a.x - b.x, a.y - b.y}; }
    Point operator * (Point a, int b){ return (Point){a.x * b, a.y * b}; }
    Point operator / (Point a, int b){ return (Point){a.x / b, a.y / b}; }
    
    double theta(Point a){ return atan2(a.y, a.x); }
    double dis(Point a, Point b){ return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }
    
    int bl[maxn];
    
    ll calc(int k, int x) {
    	int res = 1;
    	for(int i = 0; i < 3; i ++)
    		if(x != i) res *= sum[k][i];
    	return res;
    }
    
    void solve(int u){
    	int m = 0;
    	for(int i = 1 ; i <= n ; ++i){
    		if(i == u) continue;
    		b[++m] = a[i];
    	}
    	
    	for(int i = 1 ; i <= m ; ++i){
    		b[i].x -= a[u].x, b[i].y -= a[u].y;
    		b[i].k = theta(b[i]);
    		if(b[i].k <= 0) b[i].k += pi;
    	}
    	
    	sort(b + 1, b + 1 + m);
    	memset(sum, 0, sizeof(sum));
    	
    	for(int i = 1 ; i <= m ; ++i) {
    		if(b[i].y < 0 || (b[i].y == 0 && b[i].x > 0)) {
    			bl[i] = 0;
    		} else {
    			bl[i] = 1;
    		}
    		sum[bl[i]][b[i].c]++;
    	}
    	
    	for(int i = 1 ; i <= m ; ++i){
    		sum[bl[i]][b[i].c]--;
    		ans += calc(0, b[i].c) * calc(1, a[u].c);
    		ans += calc(1, b[i].c) * calc(0, a[u].c);
    		sum[bl[i] ^= 1][b[i].c]++;
    	}
    }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	scanf("%d", &n);
    	for(int i = 1 ; i <= n ; ++i){ scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].c); }
    	
    	for(int i = 1 ; i <= n ; ++i) solve(i);
    	
    	printf("%lld
    ", ans / 4);
    	return 0;
    }
    
  • 相关阅读:
    数据结构-第5章学习小结
    数据结构-第4章学习小结
    数据结构-第3章学习小结
    数据结构-第2章学习小结
    数据结构-第1章学习小结
    实验五 单元测试
    实验四 代码评审
    实验三 UML建模工具的安装和使用
    实验二 结对编程 (第二阶段)
    结对编程实验 第一阶段
  • 原文地址:https://www.cnblogs.com/tuchen/p/14275211.html
Copyright © 2020-2023  润新知