今天做了一道题(呵呵,做完我发现自己曾经做过),简直无力吐槽,为什么同一份代码G++错,而C++对,浪费我好几个小时。(不过也让我从不同的角度思考问题了)
POJ 1269 Intersecting Lines
http://poj.org/problem?id=1269
求解两条线段的关系:平行,共线,相交(求交点坐标)
分析:
AB和CD的交点是P,求之:
同理,Y:
即使是不接触相交也能用此法求之。
不过等式涉及正负号的问题(变向)
#include <cstdio> using namespace std; struct point{ int x,y; }p[5]; int multi(point p0,point p1,point p2){ return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } int abs(int x){ return x<0?-x:x; } int main(){ //freopen("cin.txt","r",stdin); int t; scanf("%d",&t); printf("INTERSECTING LINES OUTPUT\n"); while(t--){ for(int i=1;i<=4;i++) scanf("%d%d",&p[i].x,&p[i].y); int r1=multi(p[3],p[4],p[1]); int r2=multi(p[3],p[4],p[2]); int r3=multi(p[1],p[2],p[3]); int r4=multi(p[1],p[2],p[4]); if(r1==0&&r2==0){ printf("LINE\n"); } else if((p[1].x-p[2].x)*(p[3].y-p[4].y)==(p[1].y-p[2].y)*(p[3].x-p[4].x)){ printf("NONE\n"); } else { int M1=abs(r1),M2=abs(r2),M3=abs(r3),M4=abs(r4); double x,y; if(r1*r2>0){ x=(p[1].x*M2-p[2].x*M1+0.0)/(M2-M1); y=(p[1].y*M2-p[2].y*M1+0.0)/(M2-M1); } else if(r3*r4>0){ x=(p[3].x*M4-p[4].x*M3+0.0)/(M4-M3); y=(p[3].y*M4-p[4].y*M3+0.0)/(M4-M3); } else { x=(p[4].x*M3+p[3].x*M4+0.0)/(M3+M4); y=(p[4].y*M3+p[3].y*M4+0.0)/(M3+M4); } printf("POINT %.2lf %.2lf\n",x,y); } } printf("END OF OUTPUT\n"); return 0; }
简化:
如果一开始就直接使用multi(a,c,b)作为M1, multi(a,d,b)作为M2,那么计算过程自己就把不接触相交和接触相交的问题解决了。
求交点:
double x=(p[4].x*r3-p[3].x*r4)*1.0/(r3-r4); double y=(p[4].y*r3-p[3].y*r4)*1.0/(r3-r4); printf("POINT %.2lf %.2lf\n",x,y);
第二种看法:
相同的过程推出:
double x=(p[2].x*r1-p[1].x*r2)*1.0/(r2-r1); double y=(p[2].y*r1-p[1].y*r2)*1.0/(r2-r1); printf("POINT %.2lf %.2lf\n",-x,-y);惭愧的是,我暂时不能解释为什么第二种看法得到结果是正确值的相反数。