[2019HDU multi-school fourth] [HDU 6617] [D. Enveloping Convex]

Topic links: http://acm.hdu.edu.cn/showproblem.php?pid=6617

Title effect: given a convex hull \ (P \), and find the smallest \ (P \) similar and parallel to the side corresponding to the polygon, such that a given subject \ (m \) points \ (Q_I \) are the polygon included, similar to the minimum output ratio

Solution: binary answer \ (k \), consideration of how to determine the \ (P \) is amplified \ whether the (K \) times can translate this \ (m \) points so that they are within the polygon. All look as a directed line segment (counterclockwise), then \ (m \) are the points of the polygon inside the polygon when and only if they are to have left in these segments. Record of the \ (I \) edges \ (F_i \) means that if the point \ (q_ {f_i} \) on this left side, we can ensure that all points on its left side, by this \ (m after \) find points in the convex hull may be determined (O (m) \) time complexity \ \ (f_i \). So we only need to know, whether the presence of a translation vector, so that \ (m \) after translation points, all the points \ (q_ {f_i} \) are left at the \ (I \) of edges .

   So we if each edge \ ((p_i, p_ {i + 1}) \), to obtain a qualified vector set \ (\ vec {A_i} \), it can be determined whether their intersection is empty to determine the current ratio \ (k \) is legitimate. Can be found in \ (\ vec {A_i} = \ {\ vec {OA} | A \ text {is on the left of} \ vec {(p_i-q_ {f_i}, p_ {i + 1} -q_ {f_i} )} \} \) represents a half-plane, then we can solve this question by seeking to pay half plane.

   Note that the subject request is parallel to the corresponding sides, so we have the original pattern rotation \ (180 ^ {\ circ} \) do it again, extracted twice answer minimum output.

#include<bits/stdc++.h>
using namespace std;
#define N 100001
const double eps=1e-10;
int sgn(double x)
{
    if(x<-eps)return -1;
    if(x>eps)return 1;
    return 0;
}
struct Point
{
    double x,y;
    void read(){scanf("%lf%lf",&x,&y);}
    Point operator +(const Point &t)const{return {x+t.x,y+t.y};}
    Point operator -(const Point &t)const{return {x-t.x,y-t.y};}
    double operator *(const Point &t)const{return x*t.y-y*t.x;}
    Point operator *(const double t)const{return {x*t,y*t};}
    Point operator /(const double t)const{return {x/t,y/t};}
    double ang()const{return atan2(1.0*y,1.0*x);}
    double length()const{return sqrt(x*x+y*y);}
}p[N];
struct Line
{
    Point p1,p2;
    Point isct(const Line &t)const
      {
      double a=(p2-p1)*(t.p1-p1);
      double b=(p2-p1)*(p1-t.p2);
      return (t.p1*b+t.p2*a)/(a+b);
      }
}q[N],line[N];
Point cent;
bool cmpang(const Point &p1,const Point &p2)
{
    int tmp=sgn((p1-cent).ang()-(p2-cent).ang());
    if(tmp!=0)return tmp<0;
    return (p1-cent).length()<(p2-cent).length();
}
struct Polygon
{
    int n;
    Point a[N];
    void read()
      {
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
        a[i].read();
      }
    void ChangetoConvex()
      {
      for(int i=2;i<=n;i++)
        if(a[i].x<a[1].x || (a[i].x==a[1].x && a[i].y<a[1].y))
          swap(a[1],a[i]);
      cent=a[1];
      sort(a+2,a+n+1,cmpang);
      int top=2;
      for(int i=3;i<=n;i++)
        {
        while(top>=2 && (a[top]-a[top-1])*(a[i]-a[top])<=0)top--;
        a[++top]=a[i];
        }
      n=top;
      }
}P,Q;
int T,nxt[N],pre[N],f[N];
bool check(int i,Point A,Point B)
{
    return sgn((B-A)*(Q.a[pre[i]]-Q.a[i]))>=0 && sgn((B-A)*(Q.a[nxt[i]]-Q.a[i]))>=0;
}
bool Left(const Point &p,const Line &l){return sgn((l.p2-l.p1)*(p-l.p1))==1;}
bool HalfPlane(int n)
{
    int h=1,t=1;
    q[1]=line[1];
    for(int i=2;i<=n;i++)
      {
      while(h<t && !Left(p[t-1],line[i]))t--;
      while(h<t && !Left(p[h],line[i]))h++;
      if(sgn((q[t].p2-q[t].p1)*(line[i].p2-line[i].p1))==0)
        q[t]=Left(q[t].p1,line[i])?q[t]:line[i];
      else q[++t]=line[i];
      if(h<t)p[t-1]=q[t].isct(q[t-1]);
      }
    while(h<t && !Left(p[t-1],q[h]))t--;
    if(t-h<=1)return false;
    p[t]=q[t].isct(q[h]);
    double ans=0;
    for(int i=h;i<=t;i++)
      ans+=p[i]*p[(i+1-h)%(t-h+1)+h];
    return sgn(ans)>=0;
}
bool check(double k)
{
    for(int i=1;i<=P.n;i++)
      line[i]={P.a[i]*k-Q.a[f[i]],P.a[i%P.n+1]*k-Q.a[f[i]]};
    return HalfPlane(P.n);
}
double solve()
{
    int j=1;
    for(int i=1;i<=P.n;i++)
      {
      while(!check(j,P.a[i],P.a[i%P.n+1]))j=nxt[j];
      f[i]=j;
      }
    double l=0,r=1e9,mid;
    while(l+eps<r)
      {
      mid=(l+r)*0.5;
      if(check(mid))r=mid;
      else l=mid;
      }
    return l;
}
void init()
{
    double ans=1e18;
    P.read(),Q.read();
    if(Q.n==1){printf("%.6f\n",0.0);return;}
    P.ChangetoConvex();
    Q.ChangetoConvex();
    for(int i=1;i<=Q.n;i++)
      nxt[i]=i%Q.n+1,pre[i%Q.n+1]=i;
    ans=min(ans,solve());
    for(int i=1;i<=P.n;i++)
      P.a[i]=P.a[i]*(-1.0);
    ans=min(ans,solve());
    printf("%.6f\n",ans);
}
int main()
{
    scanf("%d",&T);
    while(T--)init();
}
View Code

 

   Description of \ (\ vec {A_i} \): The set point \ (q_ {f_i} \) of \ (Q \), then \ (\ vec {OA} \) satisfy the origin \ (O \) translational \ (\ vec {OA} \), he has left in the segment \ (\ vec {(p_i-Q, p_ {i + 1} -Q)} \) a. Therefore origin \ (O \) after translation \ (\ vec {OA} \), then the translation \ (\ vec {OQ} \), which is able to meet the directed line segment \ (\ vec {(p_i, p_ { left i + 1})} \) a. And \ (O + \ vec {OA} + \ vec {OQ} = O + \ vec {OQ} + \ vec {OA} = Q + \ vec {OA} \), thus \ (Q \) translation \ (\ VEC {OA} \) is able to meet the requirements.

Guess you like

Origin www.cnblogs.com/DeaphetS/p/11300827.html