hdu 6626 geometric problem(解析几何)

很容易读懂的几何题,就是非常非常难写。

要求ABS与SNTM与XYT三个图形面积相同,并且S和T分别在直线L1、L2上,并且在对应的四边形内部。输出S和T的解,若有多个,输出字典序最小的(先S的x坐标,再S的y坐标这样)。

直观来看,在非退化情形下,S和T均有一个移动的自由度,而面积有两条方程限制,应该是有唯一解的,所以只要列方程求解再判断是否满足条件即可。

而对于特殊情形,比如L1与AB边平行,这时候方程可能无解或无数解。字典序最小的解无非出现在L1、L2与各个边的交点处,所以把可能的交点全部加入再判断面积是否相等。

具体实现来说,我在S和T上各设了一个参变量,然后用定比分点算距离,再解方程。但是貌似不比标程直接高斯消元简单。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. typedef long long ll;
  5.  
  6. typedef double db;
  7. const db PI=acos(-1);
  8. const db eps=1e-10, inf=1e12;
  9.  
  10. bool eq(db x){return fabs(x)<eps;}
  11. int sgn(db x){
  12.     if (x<=-eps) return -1;
  13.     return x>=eps;
  14. }
  15.  
  16. #define Vec const vec &
  17. #define Point const point &
  18. struct vec{
  19.     db x,y;
  20.     vec():x(0),y(0){}
  21.     vec(db x, db y):x(x),y(y){} //[i] init-list is easier to use in c++1x
  22.     vec(db theta):x(cos(theta)),y(sin(theta)){}
  23.  
  24.     bool operator==(Vec v) const{return eq(x-v.x) && eq(y-v.y);}
  25.     db ang() const{return atan2(y,x);}
  26.  
  27.     vec operator+(Vec v) const{return vec(x+v.x,y+v.y);}
  28.     vec operator-(Vec v) const{return vec(x-v.x,y-v.y);}
  29.     vec operator*(db a) const{return vec(x*a,y*a);}
  30.     vec operator/(db a) const{return vec(x/a,y/a);}
  31.  
  32.     db operator|(Vec v) const{return x*v.x+y*v.y;} //dot
  33.     db operator&(Vec v) const{return x*v.y-y*v.x;} //cross
  34.     db operator!() const{return sqrt(x*x+y*y);}    //len
  35.     db operator~() const{return x*x+y*y;}    //len
  36.  
  37.     bool operator<(Vec v) const{return x==v.x?y<v.y:x<v.x;}
  38.     //rotate countclockwise
  39.     vec std() const{return *this/!*this;}
  40.     vec rot(db rad) const{return vec(x*cos(rad)-y*sin(rad), x*sin(rad)+y*cos(rad));}
  41.     vec l90() const{return vec(-y,x);}
  42.     vec r90() const{return vec(y,-x);}
  43.     vec vert() const{return (*this).l90().std();}  //l90 and standard
  44.  
  45.     void rd(){scanf("%lf%lf",&x,&y);}
  46.     void prt(){printf("%.10f %.10f",x,y);}
  47.     friend ostream& operator<<(ostream &o, Vec v){return o<<v.x<<','<<v.y;}
  48. };
  49. typedef vec point;
  50. db cross(Vec a, Vec b, Vec c){return b-a&c-a;}
  51. db dot(Vec a, Vec b, Vec c){return b-a|c-a;}
  52. point lineInt(Point p, Vec vp, Point q, Vec vq){
  53.     db t=(vq & p-q)/(vp&vq);
  54.     return p+vp*t;
  55. }
  56. db lineDis(Point p, Point s, Vec v){
  57.     return (v & p-s)/!v;
  58. }
  59.  
  60. int main(){
  61.     int T; cin>>T;
  62.     while (T--){
  63.         point A,B,M,N,X,Y,L11,L12,L21,L22;
  64.         A.rd(); B.rd(); M.rd(); N.rd(); X.rd(); Y.rd();
  65.         if (cross(A,B,M)<0) swap(A,B);
  66.         if (cross(M,N,X)<0) swap(M,N);
  67.         if (cross(Y,X,M)<0) swap(X,Y);
  68.         L11.rd(); L12.rd(); L21.rd(); L22.rd();
  69.         L12=L12-L11;
  70.         L22=L22-L21;
  71.         point C11=L11-L12*2;
  72.         point C12=L11+L12*2;
  73.         point C21=L21-L22*2;
  74.         point C22=L21+L22*2;
  75.         //w1 x + b1 = w2 x + w3 y + b2 = w4 y + b3
  76.         //(t d1 + (1-t) d2) / l0
  77.         db w1, w2, w3, w4, b1, b2, b3;
  78.         db d1=lineDis(C11,A,B-A);
  79.         db d2=lineDis(C12,A,B-A);
  80.         db l0=!(B-A);
  81.         w1=(d1-d2)*l0;
  82.         b1=d2*l0;
  83.         d1=-lineDis(C11,M,N-M);
  84.         d2=-lineDis(C12,M,N-M);
  85.         l0=!(M-N);
  86.         w2=(d1-d2)*l0;
  87.         b2=d2*l0;
  88.         d1=lineDis(C21,M,N-M);
  89.         d2=lineDis(C22,M,N-M);
  90.         w3=(d1-d2)*l0;
  91.         b2+=d2*l0;
  92.         //cout<<w3*0.5625+d2*l0<<'\n';
  93.         d1=-lineDis(C21,X,Y-X);
  94.         d2=-lineDis(C22,X,Y-X);
  95.         l0=!(Y-X);
  96.         w4=(d1-d2)*l0;
  97.         b3=d2*l0;
  98.         //(w1-w2)x - w3 y= +b2-b1
  99.         //- w2 x+(w4-w3)y= +b2-b3
  100.         bool hx=0, hy=0;
  101.         db det=(w1-w2)*(w4-w3)-w2*w3;
  102.         db dex=(b2-b1)*(w4-w3)+w3*(b2-b3);
  103.         db dey=(b2-b3)*(w1-w2)+w2*(b2-b1);
  104.         vec ansx, ansy;
  105.         if (eq(det)){
  106.             if (eq(dex) && eq(dey)){
  107.                 hx=1,hy=1;
  108.             }
  109.             else goto fail;
  110.         }
  111.         if (!hx && !hy) {
  112.             db x=dex/det,y=dey/det;
  113.             ansx=C11*x+C12*(1-x),ansy=C21*y+C22*(1-y);
  114.             if (cross(B,ansx,A)<-eps || cross(N,ansx,B)<-eps || cross(M,ansx,N)<-eps || cross(A,ansx,M)<-eps) goto fail;
  115.             if (cross(M,ansy,X)<-eps || cross(N,ansy,M)<-eps || cross(Y,ansy,N)<-eps || cross(X,ansy,Y)<-eps) goto fail;
  116.             ansx.prt(); putchar(' '); ansy.prt(); puts("");
  117.         }
  118.         if (hx || hy){
  119.         point P11=lineInt(L11,L12,A,M-A);
  120.         point P12=lineInt(L11,L12,B,N-B);
  121.         point P21=lineInt(L21,L22,X,M-X);
  122.         point P22=lineInt(L21,L22,Y,N-Y);
  123.             vector<pair<point,point> > ans;
  124.             bool f11,f12,f21,f22;
  125.             f11=f12=f21=f22=1;
  126.             if (dot(A,P11,M)*dot(M,P11,A)>0) f11=1; else P11=lineInt(L11,L12,M,M-N);
  127.             if (dot(B,P12,N)*dot(B,P12,N)>0) f12=1; else P12=lineInt(L11,L12,M,M-N);
  128.             if (dot(M,P21,X)*dot(X,P21,M)>0) f21=1; else P21=lineInt(L21,L22,M,M-N);
  129.             if (dot(N,P22,Y)*dot(Y,P22,N)>0) f22=1; else P22=lineInt(L21,L22,M,M-N);
  130.             if (f11 && f21) ans.push_back({P11,P21});
  131.             if (f11 && f22) ans.push_back({P11,P22});
  132.             if (f12 && f21) ans.push_back({P12,P21});
  133.             if (f12 && f22) ans.push_back({P12,P22});
  134.             if (!eq(w1-w2)){
  135.                 if (f11){
  136.                     db x=1-(P11-C11|C12-C11)/~(C12-C11);db y=(b2-b1-(w1-w2)*x)/(-w3);
  137.                     ans.push_back({P11,C21*y+C22*(1-y)});
  138.                 }
  139.                 if (f12){
  140.                     db x=1-(P12-C11|C12-C11)/~(C12-C11);db y=(b2-b1-(w1-w2)*x)/(-w3);
  141.                     ans.push_back({P12,C21*y+C22*(1-y)});
  142.                 }
  143.             }
  144.             if (!eq(w4-w3)){
  145.                 if (f21){
  146.                     db y=1-(P21-C21|C22-C21)/~(C22-C21);db x=(b2-b3-(w4-w3)*y)/(-w2);
  147.                     ans.push_back({C11*x+C12*(1-x),P21});
  148.                     //point t=C11*x+C12*(1-x);
  149.                     //printf("%f %f %f\n",cross(X,P21,Y),cross(N,M,t),cross(M,N,P21));
  150.                 }
  151.                 if (f22){
  152.                     db y=1-(P22-C21|C22-C21)/~(C22-C21);db x=(b2-b3-(w4-w3)*y)/(-w2);
  153.                     ans.push_back({C11*x+C12*(1-x),P22});
  154.                 }
  155.             }
  156.             auto pc=remove_if(ans.begin(),ans.end(),[&](const pair<point,point> &e){
  157.                 return 
  158.                 cross(B,e.first,A)<-eps || cross(N,e.first,B)<-eps || cross(M,e.first,N)<-eps || cross(A,e.first,M)<-eps || 
  159.                 cross(M,e.second,X)<-eps || cross(N,e.second,M)<-eps || cross(Y,e.second,N)<-eps || cross(X,e.second,Y)<-eps ||
  160.                 !eq(cross(A,B,e.first)-cross(X,e.second,Y))||!eq(cross(A,B,e.first)-cross(N,M,e.first)-cross(M,N,e.second));
  161.             });
  162.             ans.erase(pc,ans.end());
  163.             if (ans.empty()) goto fail;
  164.             sort(ans.begin(),ans.end());
  165.             ans[0].first.prt(); putchar(' '); ans[0].second.prt(); puts("");
  166.         }
  167.         continue;
  168.         fail:
  169.         puts("-1");
  170.     }

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注