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  

 

posted on 2016-03-02 20:42  Yesphet  阅读(124)  评论(0编辑  收藏  举报