zoukankan      html  css  js  c++  java
  • Gym 100531H Problem H. Hiking in the Hills 二分

    Problem H. Hiking in the Hills

    题目连接:

    http://codeforces.com/gym/100531/attachments

    Description

    Helen is hiking with her friends in a highland. Their plan is to hike from their camp A to a beautiful
    showplace B.

    Unfortunately, Helen started feeling dizzy due to altitude sickness. Help her group find a route such that
    the topmost height on that route is as small as possible.

    Input

    The input file contains full information about the landscape of a square region 106 × 106
    in the following
    format. The first line contains integer n — the number of triangles in the landscape (2 ≤ n ≤ 2000).
    Each of following n lines contains nine integers xi1, yi1, zi1, xi2, yi2, zi2, xi3, yi3, zi3 — coordinates of a
    triangle. All coordinates belong to the closed interval [0, 106
    ]. The two last lines contain three integers
    each: xA, yA, zA and xB, yB, zB — coordinates of the camp A and the showplace B.
    The given triangles are guaranteed to describe a consistent continuous landscape. Projections of triangles
    onto XY plane are non-degenerate and fill the square without overlapping. A vertex of one triangle never
    lays inside an edge of another triangle. Points A and B belong to the landscape surface and are different.

    Output

    Output a polyline route from A to B with the smallest possible topmost height. The first line should
    contain m, the number of vertices in this polyline. Each of following m lines should contain three integer
    coordinates of a polyline vertex: xi
    , yi
    , and zi
    . Vertices must be listed along the polyline, from A to B
    (including these two endpoints).
    All coordinates of polyline vertices should be integer. Each polyline edge must belong to some triangle
    from the input file (possibly, to its edge). The number of vertices in the polyline must not exceed 5n.

    Sample Input

    8

    1000000 0 0 1000000 1000000 150000 600000 600000 400000

    0 1000000 0 600000 600000 400000 600000 1000000 300000

    0 1000000 0 400000 300000 150000 600000 600000 400000

    400000 0 200000 1000000 0 0 400000 300000 150000

    400000 300000 150000 1000000 0 0 600000 600000 400000

    600000 600000 400000 1000000 1000000 150000 600000 1000000 300000

    0 0 0 400000 0 200000 400000 300000 150000

    0 1000000 0 0 0 0 400000 300000 150000

    100000 700000 37500

    900000 400000 137500

    Sample Output

    4

    100000 700000 37500

    400000 300000 150000

    900000 150000 100000

    900000 400000 137500

    Hint

    题意

    给你一个多面体,每个平面都是一个三角形

    然后给你一个A点和B点,你需要输出一个从A到B的路径,使得这条路径的最高点最低

    题解:

    首先,走点一定是可行的,所以我们就可以不用去考虑边。

    在一个三角形内的话,就连一条边。

    然后我们直接二分高度,然后每次CHECK A是否能到B 就好了

    注意精度有毒。。。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    struct node
    {
        double x,y,z;
        bool operator<(const node& p)  const
        {
            if(z==p.z&&y==p.y)return x<p.x;
            if(z==p.z)return y<p.y;
            return z<p.z;
        }
    };
    struct Tri
    {
        node p[3];
    };
    Tri tri[5006];
    map<node,int> H;
    map<int,node> T;
    int tot = 1;
    node A,B;
    vector<int> E[7000];
    int vis[7000];
    int n;
    void init()
    {
        memset(vis,0,sizeof(vis));
        H.clear();
        T.clear();
        tot = 1;
        for(int i=0;i<7000;i++)
            E[i].clear();
        memset(tri,0,sizeof(tri));
    }
    double eps = 1e-2;
    double dis(node aa,node bb)
    {
        return sqrt((aa.x-bb.x)*(aa.x-bb.x)+(aa.y-bb.y)*(aa.y-bb.y)+(aa.z-bb.z)*(aa.z-bb.z));
    }
    double area(node aa,node bb,node cc)
    {
        double l1 = dis(aa,bb);
        double l2 = dis(aa,cc);
        double l3 = dis(bb,cc);
        double pp = (l1+l2+l3)/2.0;
        return sqrt(pp*(pp-l1)*(pp-l2)*(pp-l3));
    }
    int inRan(Tri kkk,node ttt)
    {
        double a1 = area(kkk.p[0],kkk.p[1],ttt);
        double a2 = area(kkk.p[0],kkk.p[2],ttt);
        double a3 = area(kkk.p[1],kkk.p[2],ttt);
        double a4 = area(kkk.p[0],kkk.p[1],kkk.p[2]);
        if(fabs(a4-a1-a2-a3)<=eps)return 1;
        return 0;
    }
    void dfs(int x,int h)
    {
        vis[x]=1;
        for(int i=0;i<E[x].size();i++)
        {
            int v = E[x][i];
            if(vis[v])continue;
            if(T[v].z>h)continue;
            dfs(v,h);
        }
    }
    int check(double h)
    {
        if(A.z>h||B.z>h)return 0;
        memset(vis,0,sizeof(vis));
        dfs(H[A],h);
        if(vis[H[B]]==1)return 1;
        return 0;
    }
    vector<node> TTT;
    int flag = 0;
    void dfs2(int x,double h)
    {
        if(flag)return;
        TTT.push_back(T[x]);
        if(x==H[B])
        {
            flag = 1;
            cout<<TTT.size()<<endl;
            for(int i=0;i<TTT.size();i++)
                printf("%.0f %.0f %.0f
    ",TTT[i].x,TTT[i].y,TTT[i].z);
            return;
        }
        vis[x]=1;
        for(int i=0;i<E[x].size();i++)
        {
            int v = E[x][i];
            if(vis[v])continue;
            if(T[v].z>h)continue;
            dfs2(v,h);
            TTT.pop_back();
        }
    }
    int main()
    {
        freopen("hiking.in","r",stdin);
        freopen("hiking.out","w",stdout);
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<3;j++)
            {
                scanf("%lf%lf%lf",&tri[i].p[j].x,&tri[i].p[j].y,&tri[i].p[j].z);
                if(H[tri[i].p[j]]==0)
                {
                    T[tot] = tri[i].p[j];
                    H[tri[i].p[j]] = tot++;
                }
            }
            for(int j=0;j<3;j++)
            {
                for(int k=j+1;k<3;k++)
                {
                    E[H[tri[i].p[j]]].push_back(H[tri[i].p[k]]);
                    E[H[tri[i].p[k]]].push_back(H[tri[i].p[j]]);
                }
            }
        }
        scanf("%lf%lf%lf",&A.x,&A.y,&A.z);
        scanf("%lf%lf%lf",&B.x,&B.y,&B.z);
        if(H[A]==0)
        {
            T[tot] = A;
            H[A] = tot++;
            for(int i=1;i<=n;i++)
            {
                if(inRan(tri[i],A))
                {
                    for(int j=0;j<3;j++)
                    {
                        E[H[A]].push_back(H[tri[i].p[j]]);
                        E[H[tri[i].p[j]]].push_back(H[A]);
                    }
                }
            }
        }
        if(H[B]==0)
        {
            T[tot] = B;
            H[B] = tot++;
            for(int i=1;i<=n;i++)
            {
                if(inRan(tri[i],B))
                {
                    for(int j=0;j<3;j++)
                    {
                        E[H[B]].push_back(H[tri[i].p[j]]);
                        E[H[tri[i].p[j]]].push_back(H[B]);
                    }
                }
            }
        }
        double l = -2.0,r = 3000050.0;
        for(int i=1;i<=100;i++)
        {
            double mid = (l+r)/2.0;
            if(check(mid))r=mid;
            else l=mid;
        }
        memset(vis,0,sizeof(vis));
        TTT.clear();
        dfs2(H[A],r+1);
    }
  • 相关阅读:
    【GIT-精讲】从零玩转Git-基础理论
    【fmjava】 面试题突击训练-Java基础语法篇01
    【笔记】springSecurity-OAuth2.0-授权模式演示
    【难受】SpirngCloud-Alibaba-nacos跨服务器访问接口的问题
    Python编程题汇总(持续更新中……)
    Python编程题14--随机分配礼物
    Python编程题13--判断两个升序列表,其中一个是另外一个的子集
    Python编程题12--列表中比前面元素都大,比后面元素都小的数
    Python编程题11--找出100以内的质数
    Python编程题10--找出和为N的两个数
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5140539.html
Copyright © 2011-2022 走看看