• Gym102361A Angle Beats(直角三角形 计算几何)题解


    题意:

    (n)个点,(q)个询问,每次问包含询问点的直角三角形有几个

    思路:

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 8000 + 10;
    typedef long long ll;
    const ll mod = 998244353;
    typedef unsigned long long ull;
    struct Point{
        ll x, y;
        int flag;
    }be[maxn], p[maxn];
    int Qua(Point a){
        if(a.x > 0 && a.y >= 0) return 1;
        if(a.x <= 0 && a.y > 0) return 2;
        if(a.x < 0 && a.y <= 0) return 3;
        if(a.x >= 0 && a.y < 0) return 4;
    }
    int cmp1(Point a, Point b) {
    	ll d = a.x * b.y - b.x * a.y;
    	if(d == 0) {
    		return a.x < b.x;
    	}
    	else{
    		return d > 0;
    	}
    }
    bool cmp(const Point &a, const Point &b){
        int qa = Qua(a), qb = Qua(b);
        if(qa == qb){
            return cmp1(a, b);
        }
        return qa < qb;
    }
    int angle(Point a, Point b){    //爆ll
        ull now = (ull)(a.x - b.x) * (a.x - b.x) + (ull)(a.y - b.y) * (a.y - b.y);
        ull exc = a.x * a.x + a.y * a.y + b.x * b.x + b.y * b.y;
        if(now == exc) return 0;    //直角
        if(now < exc) return -1;    //锐角
        return 1;   //钝角
    }
    ll cross(Point a, Point b){
        return a.x * b.y - a.y * b.x;
    }
    ll ans[maxn];
    int main(){
    	int n, q;
    	scanf("%d%d", &n, &q);
    	int cnt = 0;
    	for(int i = 1; i <= n; i++){
    		cnt++;
    		scanf("%lld%lld", &be[cnt].x, &be[cnt].y);
    		be[cnt].flag = 0;
    		p[cnt] = be[cnt];
    	}
    	for(int i = 1; i <= q; i++){
    		cnt++;
    		scanf("%lld%lld", &be[cnt].x, &be[cnt].y);
    		be[cnt].flag = i;
    		p[cnt] = be[cnt];
    	}
    
        for(int i = n + 1; i <= cnt; i++){
            p[0] = be[i];    //直角点
            int tot = 0;
            for(int j = 1; j <= n; j++){
                p[j].x = be[j].x - be[i].x;
                p[j].y = be[j].y - be[i].y;
                p[j].flag = be[j].flag;
            }
            sort(p + 1, p + n + 1, cmp);
            for(int j = 1; j <= n; j++){
                p[j + n] = p[j];
            }
    
            int R = 2;
            for(int L = 1; L <= n; L++){
                while(R <= 2 * n){
                    if(cross(p[L], p[R]) < 0) break;
                    if(angle(p[L], p[R]) >= 0) break;
                    R++;
                }
                int tR = R;
                while(tR <= 2 * n){
                    if(cross(p[L], p[tR]) <= 0) break;
                    if(angle(p[L], p[tR]) != 0) break;
                    ans[be[i].flag]++;
                    tR++;
                }
            }
        }
    
        for(int i = 1; i <= n; i++){
            p[0] = be[i];   //非直角点
            int tot = 0;
            for(int j = 1; j <= cnt; j++){
                if(j == i) continue;
                tot++;
                p[tot].x = be[j].x - be[i].x;
                p[tot].y = be[j].y - be[i].y;
                p[tot].flag = be[j].flag;
            }
            sort(p + 1, p + tot + 1, cmp);
            for(int j = 1; j <= tot; j++){
                p[j + tot] = p[j];
            }
    
            int R = 2;
            for(int L = 1; L <= tot; L++){
                while(R <= 2 * tot){
                    if(cross(p[L], p[R]) < 0) break;
                    if(angle(p[L], p[R]) >= 0) break;
                    R++;
                }
                int tR = R;
                while(tR <= 2 * tot){
                    if(cross(p[L], p[tR]) <= 0) break;
                    if(angle(p[L], p[tR]) != 0) break;
                    if(p[L].flag && p[tR].flag == 0){
                        ans[p[L].flag]++;
                    }
                    else if(p[L].flag == 0 && p[tR].flag){
                        ans[p[tR].flag]++;
                    }
                    tR++;
                }
            }
        }
    
        for(int i = 1; i <= q; i++) printf("%lld
    ", ans[i]);
    
    	return 0;
    }
    
    
  • 相关阅读:
    OpenCV 笔记 (C++模板template)
    C++中预定义的运算符的操作对象只能是基本的数据类型
    linux-CentOS6.4下安装oracle11g详解
    Eclipse 连接MySql数据库总结
    六个创建模式之单例模式(Singleton Pattern)
    六个创建模式之抽象工厂模式(Abstract Factory Pattern)
    六个创建模式之工厂方法模式(Factory Method Pattern)
    六个创建模式之简单工厂模式(Simple Factory Pattern)
    搜狗实习面试
    Java设计模式 -- 基本原则
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11634347.html
Copyright © 2020-2023  润新知