zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    memset 还可以这样用
    搜索(DFS)
    搜索(BFS)
    最大流之sap算法
    最大流之sap算法
    String VS Cstring(字符串)
    String VS Cstring(字符串)
    Set 与 Multiset
    deque(双端队列)
    枚举 TODO
  • 原文地址:https://www.cnblogs.com/GhostReach/p/6262459.html
Copyright © 2011-2022 走看看