BZOJ2191:Splite
Description
给两个多边形,问否在平移旋转不翻转不重叠的情况下拼成一个凸多边形。
Input
每组第一行一个数N表示第一个多边形的顶点数,下接N行按顺序(逆/顺时针)给出顶点坐标,再下一行给一个数M表示第二个多边形的顶点数,下接M行按顺序给出顶点坐标。
Output
对于每组数据,输出一行0/1,1表示能,0表示不能。
Sample Input
4
0 0 0 1 1 1 1 0 4 0 0 0 1 1 1 1 0 4 0 0 0 1 1 1 1 0 4 0 0 0 1 1 1 1 0
Sample Output
1 1
HINT
对于100%的数据,N<=1000,M<=1000,顶点坐标为实数,标程精度1e-8
题解:
平面计算几何题。每次枚举相拼的两条边,在按顺序扫过两个多边形对应的变,检查是否是无缝屏接,拼好后是否是凸多边形。
注意给点的顺序不一定都是逆时针的,先按照给点的顺序扫过每一条边,记录下角度的偏转情况。若最终偏转为-2π,则为顺时针;若为2π,则为逆时针。
通过倒着排序给出的点,使两个多边形都变成是逆时针的,就可以正常做了。
代码:
1 var 2 i,j,k,l,n,m:longint; 3 a,b:array[-1000..2000,1..2]of extended; 4 tt:array[1..2]of extended; 5 e:extended; 6 function dis(x,y,xx,yy:extended):extended; 7 begin 8 exit(sqrt(sqr(x-xx)+sqr(y-yy))); 9 end; 10 function xj2(x,y:extended):extended; 11 var i,j,k,l:longint; 12 begin 13 if(abs(x)<0.0000001)and(y>0)then exit(pi/2); 14 if(abs(x)<0.0000001)and(y<0)then exit(3*pi/2); 15 if(abs(y)<0.0000001)and(x>0)then exit(0); 16 if(abs(y)<0.0000001)and(x<0)then exit(pi); 17 if(x>0)and(y>0)then exit(arctan(y/x)); 18 if(x>0)and(y<0)then exit(2*pi-arctan(-y/x)); 19 if(x<0)and(y>0)then exit(pi/2+arctan(-x/y)); 20 if(x<0)and(y<0)then exit(pi+arctan(y/x)); 21 end; 22 function xj(x,y,xx,yy,xxx,yyy:extended):extended; 23 var z1,z2:extended; 24 begin 25 z1:=xj2(x-xx,y-yy); 26 z2:=xj2(xxx-xx,yyy-yy); 27 while z2>0.0000001+z1 do z2:=z2-2*pi; 28 exit(z1-z2); 29 end; 30 function ss:longint; 31 var i,j,ii,jj,k,l:longint; 32 z1,z2,z3:extended; 33 begin 34 for i:=1 to n do 35 for j:=1 to m do 36 if abs(dis(a[i-1,1],a[i-1,2],a[i,1],a[i,2]) 37 -dis(b[j+1,1],b[j+1,2],b[j,1],b[j,2]))<0.0000001 then 38 begin 39 z1:=xj(a[i-2,1],a[i-2,2],a[i-1,1],a[i-1,2],a[i,1],a[i,2]); 40 z2:=xj(b[j+2,1],b[j+2,2],b[j+1,1],b[j+1,2],b[j,1],b[j,2]); 41 while z2>0.0000001+z1 do z2:=z2-2*pi; 42 if z1-z2>pi+0.0000001 then continue; 43 ii:=i+1; jj:=j-1; l:=0; 44 while true do 45 begin 46 z1:=xj(a[ii-2,1],a[ii-2,2],a[ii-1,1],a[ii-1,2],a[ii,1],a[ii,2]); 47 z2:=xj(b[jj+2,1],b[jj+2,2],b[jj+1,1],b[jj+1,2],b[jj,1],b[jj,2]); 48 while z2>0.0000001+z1 do z2:=z2-2*pi; 49 if z1-z2<0.0000001 then 50 begin 51 if abs(dis(a[ii-1,1],a[ii-1,2],a[ii,1],a[ii,2]) 52 -dis(b[jj+1,1],b[jj+1,2],b[jj,1],b[jj,2]))<0.0000001 then 53 begin inc(ii); dec(jj); end else begin l:=1; break; end; 54 continue; 55 end; 56 if z1-z2<pi-0.0000001 then 57 begin l:=1; break; end; 58 break; 59 end; 60 if l=0 then 61 begin 62 for k:=ii to i+n-2 do 63 if xj(a[k-1,1],a[k-1,2],a[k,1],a[k,2],a[k+1,1],a[k+1,2])>pi+0.0000001 64 then begin l:=1; break; end; 65 for k:=jj downto j-m+2 do 66 if xj(b[k+1,1],b[k+1,2],b[k,1],b[k,2],b[k-1,1],b[k-1,2])<pi-0.0000001 67 then begin l:=1; break; end; 68 if l=0 then exit(1); 69 end; 70 end; 71 exit(0); 72 end; 73 begin 74 while not eof do 75 begin 76 readln(n); 77 for i:=1 to n do readln(a[i,1],a[i,2]); 78 a[n+1]:=a[1]; a[0]:=a[n]; e:=0; 79 for i:=1 to n do 80 e:=e+xj(a[i-1,1],a[i-1,2],a[i,1],a[i,2],a[i+1,1],a[i+1,2])-pi; 81 if e>0 then 82 begin 83 for i:=1 to n div 2 do begin tt:=a[i]; a[i]:=a[n-i+1]; a[n-i+1]:=tt; end; 84 end; 85 for i:=1 to n do a[i-n]:=a[i]; 86 for i:=1 to n do a[i+n]:=a[i]; 87 readln(m); 88 for i:=1 to m do readln(b[i,1],b[i,2]); 89 b[m+1]:=b[1]; b[0]:=b[m]; e:=0; 90 for i:=1 to m do 91 e:=e+xj(b[i-1,1],b[i-1,2],b[i,1],b[i,2],b[i+1,1],b[i+1,2])-pi; 92 if e>0 then 93 begin 94 for i:=1 to m div 2 do begin tt:=b[i]; b[i]:=b[m-i+1]; b[m-i+1]:=tt; end; 95 end; 96 for i:=1 to m do b[i-m]:=b[i]; 97 for i:=1 to m do b[i+m]:=b[i]; 98 writeln(ss); 99 end; 100 end.