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
_____MildTheorem