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.
View Code
posted @ 2017-01-08 18:18  GhoStreach  阅读(268)  评论(0编辑  收藏  举报