poj1556 The Doors 2012-01-11

http://poj.org/problem?id=1556

 

 

________________________________________

将两个x坐标不同的点之间连一条边,判断是否经过墙壁,如果可行就将这条边加入图,最后计算起点到终点的最短路

 

________________________________________

  1 Program Stone;
  2 const exp=1e-8;
  3 var n,m:longint;
  4     xi:array[0..50]of real;
  5     yi:array[0..50,1..4]of real;
  6     pos:array[0..50,1..4]of longint;
  7     map:array[1..500,1..500]of real;
  8     h:array[1..500]of real;
  9     f:array[1..500]of boolean;
 10  Procedure init;
 11  var i,j:longint;
 12   begin
 13     xi[0]:=0;yi[0][1]:=5;
 14     xi[n+1]:=10;yi[n+1][1]:=5;
 15     pos[0,1]:=1;pos[n+1,1]:=2;
 16     m:=2;
 17     for i:=1 to n do
 18      begin
 19         read(xi[i]);
 20         for j:=1 to 4 do begin
 21                            read(yi[i][j]);
 22                            inc(m);pos[i,j]:=m;
 23                          end;
 24      end;
 25     for i:=1 to m do
 26      for j:=1 to m do map[i,j]:=0;
 27   end;
 28  Function cross(x1,y1,x2,y2:real):real;   //叉积
 29   begin
 30      cross:=x1*y2-x2*y1;
 31   end;
 32  Function threeout(x:real):longint;     //三出口,判断精度
 33   begin
 34      if abs(x)<exp then exit(0);             //精度之内输出0
 35      if x>0 then exit(1) else exit(-1);     
 36   end;
 37  Function between(y1,y2,y3:real):boolean;    //判断一个点是否在两个点之间
 38   Begin
 39     if threeout(y1-y3)*threeout(y1-y2)<=0 then exit(true) else exit(false);    
 40   end;
 41  Function check(x1,y1,x2,y2,x3,y3,x4,y4:real):boolean;    //判断是否相交。
 42  var s1,s2,s3,s4:longint;
 43   begin
 44     s1:=threeout(cross(x2-x1,y2-y1,x3-x1,y3-y1));
 45     s2:=threeout(cross(x2-x1,y2-y1,x4-x1,y4-y1));
 46     s3:=threeout(cross(x4-x3,y4-y3,x1-x3,y1-y3));
 47     s4:=threeout(cross(x4-x3,y4-y3,x2-x3,y2-y3));
 48     if (s1 xor s2=-2)and(s3 xor s4=-2) then exit(true);       //规范相交。
 49     if (s1=0)and(between(y3,y1,y2)) then exit(true);     //不规范相交的判断
 50     if (s2=0)and(between(y4,y1,y2)) then exit(true);
 51     if (s3=0)and(between(y1,y3,y4)) then exit(true);
 52     if (s4=0)and(between(y2,y3,y4)) then exit(true);
 53     exit(false);
 54   end;
 55  Procedure main;
 56  var i1,i2,j1,j2,k,l:longint;
 57      flag:boolean;
 58   begin
 59     for i1:=0 to n do
 60      for i2:=1 to 4 do
 61       if not(((i1=0)or(i1=n+1))and(i2>1)) then
 62       for j1:=i1+1 to n+1 do
 63        for j2:=1 to 4 do
 64        if not(((j1=0)or(j1=n+1))and(j2>1)) then
 65         begin
 66           flag:=true;
 67           for k:=i1+1 to j1-1 do
 68            begin
 69              if not((check(xi[i1],yi[i1][i2],xi[j1],yi[j1][j2],xi[k],yi[k][1],xi[k],yi[k][2]))or
 70                 (check(xi[i1],yi[i1][i2],xi[j1],yi[j1][j2],xi[k],yi[k][3],xi[k],yi[k][4])))then flag:=false;    
 71 
 72             //如果这条边与某堵墙的其中一个门相交,者这条边可以经过这堵墙。
 73            end;
 74           if flag then map[pos[i1,i2],pos[j1,j2]]:=sqrt(sqr(xi[j1]-xi[i1])+sqr(yi[j1][j2]-yi[i1][i2]));   //如果该边可行,就加入图。
 75         end;
 76   end;
 77  Procedure dijkstra;   //求最短路。
 78  var i,j,k,l:longint;
 79      s:real;
 80   begin
 81    for i:=1 to m do h[i]:=map[1,i];
 82    fillchar(f,sizeof(f),true);
 83     for i:=1 to m-2 do
 84      begin
 85        s:=10000000;
 86        for j:=2 to m do
 87         if (f[j])and(h[j]>exp)and(s-h[j]>exp) then
 88             begin
 89                s:=h[j];k:=j;
 90             end;
 91        f[k]:=false;
 92        for j:=2 to m do
 93         if (map[k,j]>exp)and((h[j]-(h[k]+map[k,j])>exp)or(abs(h[j])<exp)) then h[j]:=h[k]+map[k,j];
 94      end;
 95     writeln(h[2]:0:2); 
 96   end;
 97 Begin
 98  assign(input,'input.in');reset(input);
 99   readln(n);
100   while n<>-1 do
101    begin
102       init;
103       main;
104       dijkstra;
105       readln(n);
106    end;
107 end.
108 
109  

 

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