poj2826 An Easy Problem?! 2012-01-11
http://acm.pku.edu.cn/JudgeOnline/problem?id=2826
____________________________________________
多种情况判断。如果用pascal最后输出答案时最好加个esp,即精度。不然有可能输出-0.00。
觉得算是比较标准的判断线段相交及求出交点的模板了。虽然有点冗长。
____________________________________________
1 Program Stone; 2 const exp=1e-8; 3 type coord=record 4 x,y:real; 5 end; 6 var n,i:longint; 7 o0,o1,o2,o3,o4,o5,o6,o7,o8,oi,ox:coord; 8 flag:boolean; 9 Function cross(o1,o2,o3:coord):real; //叉积 10 begin 11 cross:=(o2.x-o1.x)*(o3.y-o1.y)-(o3.x-o1.x)*(o2.y-o1.y); 12 end; 13 Function between(y1,y2,y3:real):boolean; 14 Begin 15 if (y1-y2)*(y1-y3)<exp then between:=true else between:=false; 16 end; 17 Function judgeintersect(o1,o2,o3,o4:coord):coord; //判断相交和求出交点。 18 var s1,s2,s3,s4:real; 19 begin 20 s1:=cross(o1,o2,o3); 21 s2:=cross(o1,o2,o4); 22 s3:=cross(o3,o4,o1); 23 s4:=cross(o3,o4,o2); 24 flag:=true; 25 if (s1*s2<-exp)and(s3*s4<-exp) then 26 begin 27 judgeintersect.x:=((o3.x*s2)-(o4.x*s1))/(s2-s1); 28 judgeintersect.y:=((o3.y*s2)-(o4.y*s1))/(s2-s1); //运用规范相交公式求交点。 29 exit; 30 end; 31 if (s1=0)and(between(o3.y,o1.y,o2.y)) then begin judgeintersect:=o3;exit;end; //非规范相交,即交点为线段的某个端点。 32 if (s2=0)and(between(o4.y,o1.y,o2.y)) then begin judgeintersect:=o4;exit;end; 33 if (s3=0)and(between(o1.y,o3.y,o4.y)) then begin judgeintersect:=o1;exit;end; 34 if (s4=0)and(between(o2.y,o3.y,o4.y)) then begin judgeintersect:=o2;exit;end; 35 flag:=false; //不然就不相交。 36 end; 37 Procedure work; 38 var s:real; 39 k:longint; 40 begin 41 k:=0; 42 if (o1.y-oi.y>exp) then begin inc(k);o5:=o1;end; 43 if (o2.y-oi.y>exp) then begin inc(k);o5:=o2;end; 44 if (o3.y-oi.y>exp) then begin inc(k);o6:=o3;end; 45 if (o4.y-oi.y>exp) then begin inc(k);o6:=o4;end; 46 if k<2 then begin writeln('0.00');exit;end; 47 if o5.y-o6.y>exp then begin o7:=o5;o5:=o6;o6:=o7;end; 48 o0.x:=oi.x;o0.y:=oi.y+100; 49 if ((cross(oi,o0,o6)*cross(oi,o6,o5)>exp))and((abs(o6.x-oi.x)-abs(o5.x-oi.x))>=-exp) then 50 begin writeln('0.00');exit;end; 51 o7.x:=100000000;o7.y:=o5.y; 52 o8.x:=-100000000;o8.y:=o5.y; 53 ox:=judgeintersect(o7,o8,o6,oi); 54 s:=0; 55 o0.x:=0;o0.y:=0; 56 s:=(cross(o0,o5,oi)+cross(o0,oi,ox)+cross(o0,ox,o5))*0.5; 57 writeln(abs(s)+exp:0:2); //要加上esp 58 end; 59 Begin 60 assign(input,'input1.in');reset(input); 61 assign(output,'output.out');rewrite(output); 62 readln(n); 63 for i:=1 to n do 64 begin 65 readln(o1.x,o1.y,o2.x,o2.y,o3.x,o3.y,o4.x,o4.y); 66 oi:=judgeintersect(o1,o2,o3,o4); //求出交点。 67 if (abs(o1.x-o2.x)<exp)and(abs(o1.y-o2.y)<exp) then flag:=false; 68 if (abs(o3.x-o4.x)<exp)and(abs(o3.y-o4.y)<exp) then flag:=false; 69 if flag=false then writeln('0.00') 70 else work; 71 end; 72 close(input);close(output); 73 end. 74 75
_____MildTheorem