zoukankan      html  css  js  c++  java
  • gym 100531 三维几何+搜索

    精度有点毒, 其实可以不用double, 因为A, B必定在其中一个在三角形上,可以投影到只有x,y轴的地方叉积比较。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PII pair<int, int>
    #define PLI pair<LL, int>
    #define PLL pair<LL, LL>
    #define ull unsigned long long
    using namespace std;
    
    const int N = 5000 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-4;
    
    int dcmp(double x) {
        if(fabs(x) <= eps) return 0;
        return x < 0 ? -1 : 1;
    }
    
    struct Point3 {
        double x, y, z;
        Point3(double x=0, double y=0, double z=0):x(x), y(y), z(z) {}
        bool operator < (const Point3 &rhs) const {
            if(x == rhs.x && y == rhs.y) return z < rhs.z;
            else if(x == rhs.x) return y < rhs.y;
            else return x < rhs.x;
        }
        bool operator == (const Point3 &rhs) const {
            return dcmp(x-rhs.x)==0 && dcmp(y-rhs.y) == 0 && dcmp(z-rhs.z == 0);
        }
    };
    
    typedef Point3 Vector3;
    
    Vector3 operator + (Vector3 A, Vector3 B) {
        return Vector3(A.x+B.x, A.y+B.y, A.z+B.z);
    }
    Vector3 operator - (Vector3 A, Vector3 B) {
        return Vector3(A.x-B.x, A.y-B.y, A.z-B.z);
    }
    Vector3 operator * (Vector3 A, double p) {
        return Vector3(A.x*p, A.y*p, A.z*p);
    }
    Vector3 operator / (Vector3 A, double p) {
        return Vector3(A.x/p, A.y/p, A.z/p);
    }
    double Dot(Vector3 A, Vector3 B) {
        return A.x*B.x + A.y*B.y + A.z*B.z;
    }
    double Length(Vector3 A) {
        return sqrt(Dot(A, A));
    }
    double Angle(Vector3 A, Vector3 B) {
        return acos(Dot(A, B)/Length(A)/Length(B));
    }
    Vector3 Cross(Vector3 A, Vector3 B) {
        return Vector3(A.y*B.z-A.z*B.y, A.z*B.x-A.x*B.z, A.x*B.y-A.y*B.x);
    }
    double Area2(Point3 A, Point3 B, Point3 C) {
        return Length(Cross(B-A, C-A));
    }
    bool PointInTri(Point3 P, Point3 P0, Point3 P1, Point3 P2) {
        double area1 = Area2(P, P0, P1);
        double area2 = Area2(P, P1, P2);
        double area3 = Area2(P, P2, P0);
        return dcmp(area1+area2+area3-Area2(P0, P1, P2)) == 0;
    }
    
    int n, tot, who1, who2;
    Point3 tri[N][3], a[N*3], A, B;
    vector<int> edge[N*3];
    vector<int> path, tmp, ans;
    bool vis[N*3];
    
    inline int getId(Point3 &p) {
        return lower_bound(a+1, a+1+tot, p)-a;
    }
    
    void dfs(int u, bool &flag, double up) {
        if(flag) return;
        vis[u] = true;
        path.push_back(u);
        if(u == who2) {
            tmp = path;
            flag = true;
        }
        for(int v : edge[u]) {
            if(vis[v] || a[v].z > up) continue;
            dfs(v, flag, up);
        }
        path.pop_back();
    }
    
    bool check(double up) {
        bool flag = false;
        memset(vis, 0, sizeof(vis));
        dfs(who1, flag, up);
        return flag;
    }
    
    int main() {
        freopen("hiking.in", "r", stdin);
        freopen("hiking.out", "w", stdout);
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            for(int j = 0; j < 3; j++) {
                scanf("%lf%lf%lf", &tri[i][j].x, &tri[i][j].y, &tri[i][j].z);
                a[++tot] = tri[i][j];
            }
        }
        scanf("%lf%lf%lf", &A.x, &A.y, &A.z);
        scanf("%lf%lf%lf", &B.x, &B.y, &B.z);
        a[++tot] = A; a[++tot] = B;
        sort(a+1, a+1+tot);
        tot = unique(a+1, a+1+tot)-a-1;
        who1 = getId(A); who2 = getId(B);
        for(int i = 1; i <= n; i++) {
            int id0 = getId(tri[i][0]);
            int id1 = getId(tri[i][1]);
            int id2 = getId(tri[i][2]);
            edge[id0].push_back(id1);
            edge[id1].push_back(id0);
            edge[id0].push_back(id2);
            edge[id2].push_back(id0);
            edge[id1].push_back(id2);
            edge[id2].push_back(id1);
            if(PointInTri(A, tri[i][0], tri[i][1], tri[i][2])) {
                edge[who1].push_back(id0);
                edge[who1].push_back(id1);
                edge[who1].push_back(id2);
                edge[id0].push_back(who1);
                edge[id1].push_back(who1);
                edge[id2].push_back(who1);
            }
            if(PointInTri(B, tri[i][0], tri[i][1], tri[i][2])) {
                edge[who2].push_back(id0);
                edge[who2].push_back(id1);
                edge[who2].push_back(id2);
                edge[id0].push_back(who2);
                edge[id1].push_back(who2);
                edge[id2].push_back(who2);
            }
        }
        double low = max(A.z, B.z), high = 1e6;
        for(int i = 1; i <= 100; i++) {
            double mid = (low+high)/2;
            if(check(mid)) high = mid, ans = tmp;
            else low = mid;
        }
        printf("%d
    ", ans.size());
        for(int &t : ans) {
            printf("%d %d %d
    ", (int)(a[t].x+0.5), (int)(a[t].y+0.5), (int)(a[t].z+0.5));
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    JVM-堆内存
    生产者消费者模式-基于线程池
    nginx 499错误
    thrift入门
    RPC-基于原生java实现
    rocketMQ入门
    跟着刚哥深入学maven(通俗易懂)
    跟着刚哥学习Spring框架--AOP(五)
    跟着刚哥学习Spring框架--通过注解方式配置Bean(四)
    跟着刚哥学习Spring框架--Spring容器(二)
  • 原文地址:https://www.cnblogs.com/CJLHY/p/10038023.html
Copyright © 2011-2022 走看看