• [2019HDU多校第五场][HDU 6626][C. geometric problem]


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6626

    题目大意:给出平面上六个点(A,B,M,N,X,Y)以及两条直线(L1,L2),要求在四边形(ABNM)内,直线(L1)上选一点(S),在四边形(XYNM)内,直线(L2)上选一点(T),使得(S_{ASB}=S_{SMTN}=S_{XYT})

    题解:设(L1)交(ABNM)于点(P,Q),不妨设(S=P+tcdot (Q-P), 0leq t leq 1),则有$$2S_{ASB}=vec{AB} imes vec{AS}=vec{AB} imes (vec{AP}+tcdot vec{PQ})=vec{AB} imes vec{AP}+tcdot vec{AB} imes vec{PQ}$$

       这个式子可以转换成为(A+tcdot B)的形式。同理,三角形(SMN,MNT,XYT)均可以表示成这种形式,且(ASB,SMN)对应的(t)是(S)的坐标,不妨设为(x),另外两个三角形对应的(t)则设为(y)。这样我们就能得到$$left{egin{matrix}
    2S_{ASB}=vec{AB} imes vec{AP}+xcdot vec{AB} imes vec{PQ}\
    2S_{SMN}=vec{MN} imes vec{MP}+xcdot vec{MN} imes vec{PQ}\
    2S_{MNT}=vec{MN} imes vec{MP'}+ycdot vec{MN} imes vec{P'Q'}\
    2S_{XYT}=vec{XY} imes vec{XP'}+ycdot vec{XY} imes vec{P'Q'}
    end{matrix} ight.$$

       根据题目要求,我们就能得出$$left{egin{matrix}
    2S_{ASB}-2S_{XYT}=vec{AB} imes vec{AP}-vec{XY} imes vec{XP'}+xcdot vec{AB} imes vec{PQ}-ycdot vec{XY} imes vec{P'Q'}=0\
    2S_{ASB}-2S_{SMN}-2S_{MNT}=vec{AB} imes vec{AP}-vec{MN} imes vec{MP}-vec{MN} imes vec{MP'}+xcdot(vec{AB} imes vec{PQ}-vec{MN} imes vec{PQ})-ycdot vec{MN} imes vec{P'Q'}=0
    end{matrix} ight.$$

       这是一个二元一次方程组,当然我们也可以将其当成两条直线的标准式来看,求出他们的交点就能得出对应的答案了。

       这里要注意,这里求出来的表达式可能不会有对应的直线(比如(0cdot x+0cdot y=c eq 0)),或者会出现两直线没有交点,重合等情况,需要进行特判。另外还需要注意(x,y)解出来的值必须在([0,1])这个范围内,否则也是无解。

       另外,由于这题要求在多解时输出字典序最小的解,所以在我们求交点的时候就可以让点(P)的字典序比(Q)小,这样只要尽量让(x,y)取到最小值就好了

       由于为了防止爆精度,看到坐标范围较小,想练习手写分数运算等种种原因,这题我除了输出外都是纯整数运算,不用担心爆精度了以后感觉改代码都方便了许多(指不需要调(eps)←_←)

    #include<bits/stdc++.h>
    using namespace std;
    struct Frac
    {
        long long p,q;
        void read(){q=1,scanf("%lld",&p);}
        void simp()
          {int d=abs(__gcd(p,q));
          p/=d,q/=d;
          if(q<0)p*=-1,q*=-1;
          if(p==0)q=abs(q);
          }
        Frac operator +(const Frac &t)const
          {
          Frac res={p*t.q+t.p*q,q*t.q};
          res.simp();return res;
          }
        Frac operator -(const Frac &t)const
          {
          Frac res={p*t.q-t.p*q,q*t.q};
          res.simp();return res;
          }
        Frac operator *(const Frac &t)const
          {
          Frac res={p*t.p,q*t.q};
          res.simp();return res;
          }
        Frac operator /(const Frac &t)const
          {
          Frac res={p*t.q,q*t.p};
          res.simp();return res;
          }
        bool operator <(const Frac &t)const
          {
          return p*t.q<q*t.p;
          }
        bool operator ==(const Frac &t)const
          {
          return p==t.p && q==t.q;
          }
        void print(){printf("%.12f",1.0*p/q);}
    };
    int sgn(Frac k)
    {
        if(k.p>0)return 1;
        if(k.p<0)return -1;
        return 0;
    }
    struct Point
    {
        Frac x,y;
        void read(){x.read(),y.read();}
        Point operator +(const Point &t)const{return {x+t.x,y+t.y};}
        Point operator -(const Point &t)const{return {x-t.x,y-t.y};}
        Frac operator *(const Point &t)const{return x*t.y-y*t.x;}
        Point operator *(const Frac &t)const{return {x*t,y*t};}
        Point operator /(const Frac &t)const{return {x/t,y/t};}
        bool operator <(const Point &t)const{return x==t.x?y<t.y:x<t.x;}
        bool operator ==(const Point &t)const{return x==t.x && y==t.y;}
        void print(){x.print(),putchar(' '),y.print();}
        bool check()
          {
          if(sgn(x)<0 || sgn(y)<0)return false;
          if((Frac){1,1}<x || (Frac){1,1}<y)return false;
          return true;
          }
    }A,B,M,N,X,Y,f[5],g[5],ans[5];
    struct Line
    {
        Point p1,p2;
        void read(){p1.read(),p2.read();}
        bool check_isct(const Point &A,const Point &B)const
          {return sgn((p2-p1)*(A-p1))*sgn((p2-p1)*(B-p1))<=0;}
        Point isct_Point(const Line &t)const
          {
          Frac a=(p2-p1)*(t.p1-p1);
          Frac b=(p2-p1)*(p1-t.p2);
          return (t.p1*b+t.p2*a)/(a+b);
          }
    }L1,L2;
    struct Line_Standard
    {
        Frac A,B,C;
        bool check(){return sgn(A) || sgn(B) || !sgn(C);}
        bool check_isct(const Line_Standard &t)const
          {
          Frac tmp=A*t.B-B*t.A;
          if(sgn(tmp))return true;
          return sgn(C*t.B-B*t.C)==0;
          }
        Point isct_Point(const Line_Standard &t)const
          {
          Frac tmp=A*t.B-B*t.A;
          if(!sgn(tmp))
            {
            if(sgn(C)==0)return {{0,1},{0,1}};
            if(sgn(B)==0)return {{0,1},{1,1}};
            if(sgn(A)==0)return {{1,1},{0,1}};
            }
          return {(B*t.C-C*t.B)/tmp,(C*t.A-A*t.C)/tmp};
          }
        void print()
          {
          A.print(),putchar(' ');
          B.print(),putchar(' ');
          C.print(),putchar('
    ');
          }
    }h1,h2;
    int T,cnt;
    void rua(const Line &L,const Point &A,const Point &B,const int &lim)
    {
        if(L.check_isct(A,B) && sgn((L.p2-L.p1)*(A-B)) && cnt<lim)
          if(!(L.isct_Point({A,B})==f[cnt]) || cnt==lim-2)
            f[++cnt]=L.isct_Point({A,B});
    }
    void cal(const Point &A,const Point &B,const Point &C,const Point &D)
    {
        Frac st=(B-A)*(C-A);
        Frac delta=(B-A)*(D-C);
        Frac ed=(B-A)*(D-A);
        if(sgn(st)<0 || sgn(ed)<0)
          st.p=-st.p,delta.p=-delta.p;
        g[++cnt]={st,delta};
    }
    void print(const Point &P)
    {
        Point S=f[1]+(f[2]-f[1])*P.x;
        Point T=f[3]+(f[4]-f[3])*P.y;
        S.print(),putchar(' ');
        T.print(),putchar('
    ');
    }
    void init()
    {
        cnt=0;
        A.read(),B.read();
        M.read(),N.read();
        X.read(),Y.read();
        L1.read(),L2.read();
        rua(L1,A,B,2),rua(L1,B,N,2);
        rua(L1,N,M,2),rua(L1,M,A,2);
        rua(L2,X,Y,4),rua(L2,Y,N,4);
        rua(L2,N,M,4),rua(L2,M,X,4);
        if(f[2]<f[1])swap(f[1],f[2]);
        if(f[4]<f[3])swap(f[3],f[4]);
        cnt=0;
        cal(A,B,f[1],f[2]);
        cal(M,N,f[1],f[2]);
        cal(M,N,f[3],f[4]);
        cal(X,Y,f[3],f[4]);
        h1={g[1].y,(Frac){0,1}-g[4].y,g[1].x-g[4].x};
        h2={g[1].y-g[2].y,(Frac){0,1}-g[3].y,g[1].x-g[2].x-g[3].x};
        if(!h1.check() || !h2.check())
          {printf("-1
    ");return;}
        cnt=0;
        Frac tmp=h1.A*h2.B-h1.B*h2.A;
        if(sgn(tmp)==0)
          {
          if(sgn(h1.C*h2.B-h1.B*h2.C))
            {printf("-1
    ");return;}
          if(!sgn(h1.A) && !sgn(h1.B))
            swap(h1,h2);
          if(h1.check_isct({{1,1},{0,1},{0,1}}))
            ans[++cnt]=h1.isct_Point({{1,1},{0,1},{0,1}});
          if(h1.check_isct({{0,1},{1,1},{0,1}}))
            ans[++cnt]=h1.isct_Point({{0,1},{1,1},{0,1}});
          if(h1.check_isct({{0,1},{1,1},{-1,1}}))
            ans[++cnt]=h1.isct_Point({{0,1},{1,1},{-1,1}});
          if(h1.check_isct({{1,1},{0,1},{-1,1}}))
            ans[++cnt]=h1.isct_Point({{1,1},{0,1},{-1,1}});
          for(int i=1;i<=cnt;i++)
            if(ans[i].check())
              {print(ans[i]);return;}
          printf("-1
    ");
          return;
          }
        ans[++cnt]=h1.isct_Point(h2);
        if(ans[1].check())
          {print(ans[1]);return;}
        printf("-1
    ");
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)init();
    }
    View Code
  • 相关阅读:
    目录和文件的权限设置方法
    logstash5 单实例多配置文件实现
    elasticsearch 使用快照方式迁移数据
    mysql 主库有数据通过锁库做主从
    mfs挂载
    web页面性能分析一些网址
    centos7 ffmpeg安装
    (转)在 Windows 上安装Rabbit MQ 指南
    (转)TeamCity配置笔记
    (转)分布式缓存GemFire架构介绍
  • 原文地址:https://www.cnblogs.com/DeaphetS/p/11324848.html
Copyright © 2020-2023  润新知